├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── LICENSE
├── README.md
└── src
├── cache.cpp
├── cache.h
├── eversticky.pro
├── helpers
├── misc_helpers.cpp
├── misc_helpers.h
├── xml_helpers.cpp
└── xml_helpers.h
├── icon
├── appicon.ico
├── appicon.svg
├── sizegripicon.svg
├── trayicon.svg
├── trayicon_black.ico
└── trayicon_white.ico
├── main.cpp
├── note.cpp
├── note.h
├── note_controller.cpp
├── note_controller.h
├── note_formatter.cpp
├── note_formatter.h
├── note_sync_controller.cpp
├── note_sync_controller.h
├── qevercloud
├── AsyncResult.cpp
├── AsyncResult.h
├── EventLoopFinisher.cpp
├── EventLoopFinisher.h
├── EverCloudException.cpp
├── EverCloudException.h
├── InkNoteImageDownloader.cpp
├── InkNoteImageDownloader.h
├── Optional.h
├── QEverCloud.h
├── QEverCloudOAuth.h
├── exceptions.cpp
├── exceptions.h
├── export.h
├── generated
│ ├── EDAMErrorCode.h
│ ├── constants.cpp
│ ├── constants.h
│ ├── services.cpp
│ ├── services.h
│ ├── types.cpp
│ ├── types.h
│ └── types_impl.h
├── globals.cpp
├── globals.h
├── http.cpp
├── http.h
├── impl.h
├── oauth.cpp
├── oauth.h
├── qt4helpers.h
├── services_nongenerated.cpp
├── thrift.h
├── thumbnail.cpp
└── thumbnail.h
├── resources.qrc
├── settings.cpp
├── settings.h
├── style
├── about_stylesheet.qss
└── note_stylesheet.qss
└── ui
├── about_widget.cpp
├── about_widget.h
├── note_header.cpp
├── note_header.h
├── note_header_text_edit.cpp
├── note_header_text_edit.h
├── note_scroll_area.cpp
├── note_scroll_area.h
├── note_title_bar.cpp
├── note_title_bar.h
├── note_widget.cpp
├── note_widget.h
├── settings_widget.cpp
├── settings_widget.h
├── tray_icon.cpp
├── tray_icon.h
└── webview
├── js_interface.cpp
├── js_interface.h
├── note_webview.cpp
├── note_webview.css
├── note_webview.h
├── note_webview.js
├── note_webview_helpers.js
└── note_webview_keyhandler.js
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. Ubuntu 20.04, Debian 11]
28 | - Version [e.g. v0.95.2]
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # EverSticky
2 |
3 |
4 |
5 | A Linux open-source sticky note client that syncs to Evernote. Displays rich text formatting.
6 |
7 | ## Installation and running
8 |
9 | Supports Ubuntu 20.04 and greater. Unlikely to work on older Ubuntu versions.
10 |
11 | [Find the Linux installation guide here.](https://eversticky.joeeey.com/install)
12 |
13 | ### Compiling from source
14 |
15 | > IMPORTANT NOTE: You will need a production Evernote API key to compile the application and be able to see and alter notes you currently store on Evernote. This secret (along with the desired domain and key) needs to be provided at the top of `./src/eversticky.pro`.
16 |
17 | Install build dependencies:
18 | ```
19 | sudo apt install build-essential qt5-default qtwebengine5-dev libqt5x11extras5-dev libxpm-dev
20 | ```
21 |
22 | From the root of the repo run the following commands:
23 | ```
24 | mkdir src/build
25 | cd src/build
26 | qmake ../eversticky.pro
27 | make
28 | ```
29 | This produces the executable binary `./eversticky` in the current directory.
30 |
31 | ## Bugs
32 | This project is still in its early days and bugs are expected. Open an issue if you encounter some unexpected behaviour (after making sure one hasn't already been raised).
33 |
34 | ## License
35 | `src/qevercloud` licensed under MIT terms. Consists of `v4.0.0` release from @d1vanov's fork (https://github.com/d1vanov/QEverCloud), plus two patches ([66671bf](https://github.com/itsmejoeeey/eversticky/commit/66671bf4ffc03c4d7ed64227249971be2b35a492), [74b9b98](https://github.com/itsmejoeeey/eversticky/commit/74b9b98d67a9370a34e9b0d0a073482c0657bb3f)).
36 |
37 | For all other code see `LICENSE`
38 |
--------------------------------------------------------------------------------
/src/cache.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the eversticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef CACHE_H
19 | #define CACHE_H
20 |
21 | #include
22 |
23 | #include
24 | #include
25 |
26 | #include
27 |
28 | #include "note.h"
29 |
30 |
31 | struct queueItem {
32 | int id;
33 | QString type;
34 | Note note;
35 | };
36 |
37 | struct noteItem {
38 | int pos_x;
39 | int pos_y;
40 | int size_x;
41 | int size_y;
42 | int scroll_x;
43 | int scroll_y;
44 | };
45 |
46 | class Cache
47 | {
48 | public:
49 | static QSqlDatabase openDatabase();
50 | static void closeDatabase();
51 | static void deleteDatabase();
52 | static QString getDatabasePath();
53 |
54 | static void emptySyncTable();
55 | static void insertSyncTable(Note note);
56 | static std::optional retrieveFromSyncTable(qevercloud::Guid guid);
57 | static std::vector retrieveAllFromSyncTable();
58 |
59 | static int countQueueTableRows();
60 | static void deleteQueueTable(Note note);
61 | static void deleteFromQueueTable(int id);
62 | static void emptyQueueTable();
63 | static void insertQueueTable(Note note);
64 | static void removeGuidFromQueueTable(qevercloud::Guid guid);
65 | static std::optional retrieveFromQueueTable(qevercloud::Guid guid);
66 | static std::vector retrieveAllFromQueueTable();
67 | static std::vector retrieveNewFromQueueTable();
68 |
69 | static void deleteFromNotesTable(qevercloud::Guid guid);
70 | static void insertNotesTable(QString guid, int screens, int res_x, int res_y, int pos_x, int pos_y, int size_x, int size_y);
71 | static noteItem retrieveFromNotesTable(qevercloud::Guid guid, int screens, int res_x, int res_y);
72 | static void updateGuidInNotesTable(qevercloud::Guid oldGuid, qevercloud::Guid newGuid);
73 | };
74 |
75 | #endif // CACHE_H
76 |
--------------------------------------------------------------------------------
/src/eversticky.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 | TARGET = eversticky
3 |
4 | DEFINES += \
5 | APP_VERSION=\\\"0.96.0\\\" \
6 | \
7 | ## API_DOMAIN
8 | # Can be either 'www.evernote.com' or 'sandbox.evernote.com' for testing
9 | # --> If error 'Host requires authentication' you must go to 'https://dev.evernote.com/support/'
10 | # to request activation of your API key on our production service.
11 | API_HOST=\\\"XXXXXXXXXXXXXXXX\\\" \
12 | #
13 | ## API_KEY
14 | # Typically The username of the user than owns the API key
15 | API_KEY=\\\"XXXXXXXXXXXXXXXX\\\" \
16 | #
17 | ## API_SECRET
18 | # The 16-digit API key
19 | API_SECRET=\\\"XXXXXXXXXXXXXXXX\\\"
20 |
21 | CONFIG += c++17
22 |
23 | # Ensure Qt WebKit is not required as a dependency
24 | DEFINES += QEVERCLOUD_USE_QT_WEB_ENGINE
25 |
26 | greaterThan(QT_MAJOR_VERSION, 4): QT += core gui network sql webenginewidgets widgets x11extras xml
27 |
28 | SOURCES += \
29 | main.cpp \
30 | helpers/misc_helpers.cpp \
31 | helpers/xml_helpers.cpp \
32 | note_formatter.cpp \
33 | cache.cpp \
34 | note_sync_controller.cpp \
35 | settings.cpp \
36 | ui/about_widget.cpp \
37 | ui/note_header.cpp \
38 | ui/note_header_text_edit.cpp \
39 | ui/note_scroll_area.cpp \
40 | ui/note_title_bar.cpp \
41 | note.cpp \
42 | note_controller.cpp \
43 | ui/note_widget.cpp \
44 | ui/settings_widget.cpp \
45 | ui/tray_icon.cpp \
46 | ui/webview/js_interface.cpp \
47 | ui/webview/note_webview.cpp \
48 | #
49 | qevercloud/AsyncResult.cpp \
50 | qevercloud/EventLoopFinisher.cpp \
51 | qevercloud/EverCloudException.cpp \
52 | qevercloud/exceptions.cpp \
53 | qevercloud/globals.cpp \
54 | qevercloud/http.cpp \
55 | qevercloud/InkNoteImageDownloader.cpp \
56 | qevercloud/oauth.cpp \
57 | qevercloud/services_nongenerated.cpp \
58 | qevercloud/thumbnail.cpp \
59 | qevercloud/generated/constants.cpp \
60 | qevercloud/generated/services.cpp \
61 | qevercloud/generated/types.cpp
62 |
63 | HEADERS += \
64 | cache.h \
65 | helpers/misc_helpers.h \
66 | helpers/xml_helpers.h \
67 | note.h \
68 | note_controller.h \
69 | note_formatter.h \
70 | note_sync_controller.h \
71 | settings.h \
72 | ui/about_widget.h \
73 | ui/note_header.h \
74 | ui/note_header_text_edit.h \
75 | ui/note_scroll_area.h \
76 | ui/note_title_bar.h \
77 | ui/note_widget.h \
78 | ui/settings_widget.h \
79 | ui/tray_icon.h \
80 | ui/webview/js_interface.h \
81 | #
82 | qevercloud/AsyncResult.h \
83 | qevercloud/EventLoopFinisher.h \
84 | qevercloud/EverCloudException.h \
85 | qevercloud/exceptions.h \
86 | qevercloud/export.h \
87 | qevercloud/globals.h \
88 | qevercloud/http.h \
89 | qevercloud/impl.h \
90 | qevercloud/InkNoteImageDownloader.h \
91 | qevercloud/oauth.h \
92 | qevercloud/Optional.h \
93 | qevercloud/QEverCloud.h \
94 | qevercloud/QEverCloudOAuth.h \
95 | qevercloud/qt4helpers.h \
96 | qevercloud/thrift.h \
97 | qevercloud/thumbnail.h \
98 | qevercloud/generated/constants.h \
99 | qevercloud/generated/EDAMErrorCode.h \
100 | qevercloud/generated/services.h \
101 | qevercloud/generated/types.h \
102 | qevercloud/generated/types_impl.h \
103 | ui/webview/note_webview.h
104 |
105 | DISTFILES += \
106 | style/note_stylesheet.qss
107 |
108 | RESOURCES += \
109 | resources.qrc \
110 | ui/webview/note_webview.css \
111 | ui/webview/note_webview.js \
112 | ui/webview/note_webview_helpers.js \
113 | ui/webview/note_webview_keyhandler.js
114 |
115 | LIBS += \
116 | -lX11
117 |
118 | INCLUDEPATH += \
119 | qevercloud
120 |
--------------------------------------------------------------------------------
/src/helpers/misc_helpers.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include "misc_helpers.h"
19 |
20 | #include
21 |
22 |
23 | namespace helpers
24 | {
25 | namespace misc
26 | {
27 | QString random_hex_string(unsigned int length)
28 | {
29 | const char charset[] = "0123456789"
30 | "abcdef";
31 | const unsigned char maxIndex = (sizeof(charset) - 1);
32 |
33 | std::string str(length,0);
34 | std::generate_n(str.begin(), length, [&]() -> char {
35 | return charset[rand() % maxIndex];
36 | });
37 |
38 | return QString::fromStdString(str);
39 | }
40 | } // namespace misc
41 | } // namespace helpers
42 |
--------------------------------------------------------------------------------
/src/helpers/misc_helpers.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef MISC_HELPERS_H
19 | #define MISC_HELPERS_H
20 |
21 | #include
22 |
23 | #include
24 |
25 |
26 | namespace helpers
27 | {
28 | namespace misc
29 | {
30 | QString random_hex_string(unsigned int length);
31 |
32 | } // namespace misc
33 | } // namespace helpers
34 |
35 | #endif // MISC_HELPERS_H
36 |
--------------------------------------------------------------------------------
/src/helpers/xml_helpers.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include "xml_helpers.h"
19 |
20 | #include
21 |
22 |
23 | namespace helpers
24 | {
25 | namespace xml
26 | {
27 | QDomElement findFirstElementOfTagMatchingAttribute(const QString& tag_name, const QString& attribute_name, const QString& attribute_value, QList elems)
28 | {
29 | QList next_elems = QList();
30 |
31 | for(int i = 0; i < elems.size(); i++) {
32 | QDomElement elem = elems.at(i);
33 | if( elem.tagName() == tag_name && elem.attribute(attribute_name) == attribute_value)
34 | return elem;
35 |
36 | QDomNodeList append_list = elem.childNodes();
37 | for(int n = 0; n < append_list.size(); n++) {
38 | next_elems.append(append_list.at(n).toElement());
39 | }
40 | }
41 |
42 | return findFirstElementOfTagMatchingAttribute(tag_name, attribute_name, attribute_value, next_elems);
43 | }
44 |
45 | void findAllElements(const QDomElement elem, QList& foundElements)
46 | {
47 | foundElements.append(elem);
48 |
49 | QDomElement child = elem.firstChildElement();
50 | while(!child.isNull()) {
51 | findAllElements(child, foundElements);
52 | child = child.nextSiblingElement();
53 | }
54 | }
55 |
56 | void deleteAllAttributes(QDomElement& element)
57 | {
58 | while(element.attributes().size() > 0) {
59 | QDomAttr attribute = element.attributes().item(0).toAttr();
60 | element.removeAttribute(attribute.name());
61 | }
62 | }
63 |
64 | void deleteAllChildren(QDomNode& node) {
65 | QDomNodeList childNodes = node.childNodes();
66 | while(!childNodes.isEmpty()) {
67 | QDomNode childNode = childNodes.at(0);
68 | deleteNode(childNode);
69 | }
70 | }
71 |
72 | void deleteNode(QDomNode& node)
73 | {
74 | node.parentNode().removeChild(node);
75 | }
76 |
77 | QStringList getAllAttributeNames(QDomElement& element)
78 | {
79 | QStringList output;
80 | QDomNamedNodeMap attributes = element.attributes();
81 | for(int i = 0; i < attributes.size(); i++) {
82 | output.append(attributes.item(i).toAttr().name());
83 | }
84 |
85 | return output;
86 | }
87 | } // namespace xml
88 | } // namespace helpers
89 |
--------------------------------------------------------------------------------
/src/helpers/xml_helpers.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef XML_HELPERS_H
19 | #define XML_HELPERS_H
20 |
21 | #include
22 | #include
23 |
24 |
25 | namespace helpers
26 | {
27 | namespace xml
28 | {
29 | QDomElement findFirstElementOfTagMatchingAttribute(const QString& tag_name, const QString& attribute_name, const QString& attribute_value, QList elems);
30 | void findAllElements(const QDomElement elem, QList& foundElements);
31 |
32 | void deleteAllAttributes(QDomElement& element);
33 | void deleteAllChildren(QDomNode& node);
34 | void deleteNode(QDomNode& node);
35 |
36 | QStringList getAllAttributeNames(QDomElement& element);
37 |
38 | } // namespace xml
39 | } // namespace misc
40 |
41 | #endif // XML_HELPERS_H
42 |
--------------------------------------------------------------------------------
/src/icon/appicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsmejoeeey/eversticky/ca64d34fd955615c6e305d9eda38cf2db7336af8/src/icon/appicon.ico
--------------------------------------------------------------------------------
/src/icon/appicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
97 |
--------------------------------------------------------------------------------
/src/icon/sizegripicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
63 |
--------------------------------------------------------------------------------
/src/icon/trayicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
62 |
--------------------------------------------------------------------------------
/src/icon/trayicon_black.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsmejoeeey/eversticky/ca64d34fd955615c6e305d9eda38cf2db7336af8/src/icon/trayicon_black.ico
--------------------------------------------------------------------------------
/src/icon/trayicon_white.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itsmejoeeey/eversticky/ca64d34fd955615c6e305d9eda38cf2db7336af8/src/icon/trayicon_white.ico
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include "note_controller.h"
25 |
26 |
27 | int main(int argc, char **argv)
28 | {
29 | QApplication app (argc, argv);
30 | app.setApplicationName("eversticky");
31 | app.setQuitOnLastWindowClosed(false);
32 |
33 | // Show timestamp in logging output
34 | qSetMessagePattern("[%{time}] %{message}");
35 |
36 | const int numScreens = app.screens().length();
37 | const QRect screenSize = app.primaryScreen()->virtualGeometry();
38 | // *.* Where the magic happens *.*
39 | new NoteController(numScreens, screenSize.width(), screenSize.height());
40 |
41 | return app.exec();
42 | }
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/note.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include "note.h"
19 |
20 | #include
21 |
22 |
23 | Note::Note(qevercloud::Guid guid, int usn, QString title, QString content) :
24 | guid(guid), usn(usn), title(title), content(content)
25 | {
26 | changed = false;
27 | new_note = false;
28 | }
29 |
30 | Note::Note() {
31 | changed = false;
32 | new_note = true;
33 | }
34 |
--------------------------------------------------------------------------------
/src/note.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef NOTE_H
19 | #define NOTE_H
20 |
21 | #include
22 |
23 | class Note
24 | {
25 | public:
26 | Note(qevercloud::Guid guid, int usn, QString title, QString content);
27 | Note();
28 |
29 | qevercloud::Guid guid;
30 | int usn;
31 | QString title;
32 | QString content;
33 | bool changed;
34 | bool new_note;
35 | };
36 |
37 | #endif // NOTE_H
38 |
--------------------------------------------------------------------------------
/src/note_controller.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef NOTECONTROLLER_H
19 | #define NOTECONTROLLER_H
20 |
21 | #include
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include "cache.h"
30 | #include "note.h"
31 | #include "note_sync_controller.h"
32 | #include "ui/tray_icon.h"
33 |
34 |
35 | class NoteWidget;
36 |
37 | class NoteController : public QObject
38 | {
39 | Q_OBJECT
40 |
41 | public:
42 | NoteController(int screens, int screenWidth, int screenHeight);
43 | ~NoteController();
44 |
45 | NoteWidget* createNote();
46 | NoteWidget* createNote(Note *note);
47 | NoteWidget* createNote(Note* note_model, noteItem size);
48 |
49 | bool isAuthorised();
50 |
51 | void syncAllNoteModels();
52 |
53 | void bringAllToFront();
54 | void closeAllNotes();
55 | void updateNoteDimensions(qevercloud::Guid guid, int x, int y, int width, int height);
56 |
57 | void logoutPrepare();
58 | void showLogoutDialog();
59 |
60 | public slots:
61 | void login();
62 | void showNotes();
63 | void periodicUpdate();
64 |
65 | private:
66 | tAuthState state;
67 |
68 | NoteSyncController* noteSyncController;
69 | TrayIcon *trayIcon;
70 |
71 | std::vector notes;
72 | int noteCount;
73 |
74 | int screens;
75 | int screenWidth;
76 | int screenHeight;
77 |
78 | void hardLogout();
79 | void softLogout();
80 |
81 | bool isNoteCreated(qevercloud::Guid noteGuid);
82 |
83 | void noteDestroyed(NoteWidget *note);
84 | };
85 |
86 | #endif // NOTECONTROLLER_H
87 |
--------------------------------------------------------------------------------
/src/note_formatter.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include "note_formatter.h"
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include "helpers/xml_helpers.h"
25 |
26 |
27 | NoteFormatter::NoteFormatter(QString input_text) : inputText(input_text) {
28 |
29 | };
30 |
31 | QString NoteFormatter::standardiseInput()
32 | {
33 | QDomDocument doc;
34 | doc.setContent(inputText);
35 |
36 | QDomElement body = doc.elementsByTagName("en-note").at(0).toElement();
37 |
38 | // If note contains nothing, return empty ENML note.
39 | // --> This ensures has a child div so that initial user text
40 | // is inserted in the correct place (not in the )
41 | if(body.childNodes().size() <= 0) {
42 | return createEmptyENML();
43 | }
44 |
45 | QString output_str;
46 | QTextStream stream(&output_str);
47 | body.save(stream, 0);
48 |
49 | return enmlXmlHeader + output_str;
50 | }
51 |
52 | QString NoteFormatter::createEmptyENML()
53 | {
54 | return enmlXmlHeader + "\n
\n \n
\n";
55 | }
56 |
57 | /*
58 | * Convert ENML (XML) note content to valid HTML
59 | */
60 | QString NoteFormatter::convertFromEML()
61 | {
62 | QDomDocument doc;
63 | doc.setContent(inputText);
64 |
65 | // Convert ENML "en-note" top-level element to a div.
66 | QDomElement body = doc.elementsByTagName("en-note").at(0).toElement();
67 | body.setTagName("div");
68 | body.setAttribute("id", "en-note");
69 |
70 | // Convert ENML "en-todo" elements to html checkboxes.
71 | QDomNodeList todoElements = doc.elementsByTagName("en-todo");
72 | while(todoElements.size() > 0) {
73 | QDomElement todoElement = todoElements.at(0).toElement();
74 |
75 | // This is a hacky solution to allow the checkbox to be selected by the user.
76 | todoElement.setTagName("input");
77 | todoElement.setAttribute("class", "en-todo");
78 | // Set the image to an empty pixel (see: https://stackoverflow.com/a/14115340/3213602).
79 | // This prevents the 'missing-image' icon from appearing.
80 | todoElement.setAttribute("src", "data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=");
81 | todoElement.setAttribute("type", "image");
82 |
83 | // Only keep 'checked' attribute if true, inferred false otherwise.
84 | QString checked = todoElement.attribute("checked");
85 | if(checked != "true") {
86 | todoElement.removeAttribute("checked");
87 | }
88 | }
89 |
90 | // Convert ENML "en-media" elements to html placeholders
91 | QDomNodeList mediaElements = doc.elementsByTagName("en-media");
92 | while(mediaElements.size() > 0) {
93 | QDomElement mediaElement = mediaElements.at(0).toElement();
94 |
95 | mediaElement.setTagName("img");
96 | mediaElement.setAttribute("class", "en-media unsupported");
97 |
98 | for(int i = 0; i < validMediaAttributes.size(); i++) {
99 | QString attribute_name = validMediaAttributes.at(i);
100 | QString attribute_value = mediaElement.attribute(validMediaAttributes.at(i));
101 | if(!attribute_value.isNull()) {
102 | mediaElement.setAttribute("data-" + attribute_name, attribute_value);
103 | mediaElement.removeAttribute(attribute_name);
104 | }
105 | }
106 | }
107 |
108 | // Convert ENML "en-crypt" elements to html placeholders
109 | QDomNodeList cryptElements = doc.elementsByTagName("en-crypt");
110 | while(cryptElements.size() > 0) {
111 | QDomElement cryptElement = cryptElements.at(0).toElement();
112 |
113 | cryptElement.setTagName("img");
114 | cryptElement.setAttribute("class", "en-crypt unsupported");
115 |
116 | for(int i = 0; i < validCryptAttributes.size(); i++) {
117 | QString attribute_name = validCryptAttributes.at(i);
118 | QString attribute_value = cryptElement.attribute(validCryptAttributes.at(i));
119 | if(!attribute_value.isNull()) {
120 | cryptElement.setAttribute("data-" + attribute_name, attribute_value);
121 | cryptElement.removeAttribute(attribute_name);
122 | }
123 | }
124 | }
125 |
126 | // Save to string
127 | QString output_str;
128 | QTextStream stream(&output_str);
129 | body.save(stream, 0);
130 |
131 | return output_str;
132 | }
133 |
134 | /*
135 | * Convert HTML note content to ENML (XML)
136 | */
137 | QString NoteFormatter::convertToEML()
138 | {
139 | QDomDocument doc;
140 | doc.setContent(inputText);
141 |
142 | // Get parent element
143 | QDomElement parent = helpers::xml::findFirstElementOfTagMatchingAttribute("div", "id", "en-note", QList() << doc.documentElement());
144 | parent.setTagName("en-note");
145 | helpers::xml::deleteAllAttributes(parent);
146 |
147 | QList elements;
148 | helpers::xml::findAllElements(parent, elements);
149 | // Loop through and check each element
150 | for(int i = 0; i < elements.size(); i++) {
151 | QDomElement element = elements.at(i);
152 |
153 | // Convert ENML "en-todo" elements to html checkboxes.
154 | if(element.tagName() == "input" && element.attribute("class") == "en-todo") {
155 | element.setTagName("en-todo");
156 | element.removeAttribute("class");
157 | element.removeAttribute("src");
158 | element.removeAttribute("type");
159 | }
160 |
161 | // Convert ENML "en-media" elements to html placeholders
162 | if(element.tagName() == "img" && element.attribute("class").contains("en-media")) {
163 | element.setTagName("en-media");
164 | for(int i = 0; i < validMediaAttributes.size(); i++) {
165 | QString attribute_name = validMediaAttributes.at(i);
166 | QString attribute_value = element.attribute("data-" + attribute_name);
167 | if(!attribute_value.isNull()) {
168 | element.setAttribute(attribute_name, attribute_value);
169 | element.removeAttribute("data-" + attribute_name);
170 | }
171 | }
172 | helpers::xml::deleteAllChildren(element);
173 | }
174 |
175 | // Convert ENML "en-crypt" elements to html placeholders
176 | if(element.tagName() == "img" && element.attribute("class").contains("en-crypt")) {
177 | element.setTagName("en-crypt");
178 | for(int i = 0; i < validCryptAttributes.size(); i++) {
179 | QString attribute_name = validCryptAttributes.at(i);
180 | QString attribute_value = element.attribute("data-" + validCryptAttributes.at(i));
181 | if(!attribute_value.isNull()) {
182 | element.setAttribute(attribute_name, attribute_value);
183 | element.removeAttribute("data-" + attribute_name);
184 | }
185 | }
186 | helpers::xml::deleteAllChildren(element);
187 | }
188 |
189 | // Remove invalid attributes
190 | QStringList attributeNames = helpers::xml::getAllAttributeNames(element);
191 | QSet deleteAttributes = attributeNames.toSet().intersect(invalidAttributes.toSet());
192 | for(QSet::iterator i = deleteAttributes.begin(); i != deleteAttributes.end(); ++i) {
193 | element.removeAttribute(*i);
194 | }
195 |
196 | // Remove invalid tags
197 | if(!validTags.contains(element.tagName())) {
198 | helpers::xml::deleteNode(element);
199 | }
200 | }
201 |
202 | // Save to string
203 | QString output_str;
204 | QTextStream stream(&output_str);
205 | parent.save(stream, 0);
206 |
207 | output_str = enmlXmlHeader + output_str;
208 |
209 | return output_str;
210 | }
211 |
--------------------------------------------------------------------------------
/src/note_formatter.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef NOTEFORMATTER_H
19 | #define NOTEFORMATTER_H
20 |
21 | #include
22 | #include
23 |
24 |
25 | static const QString enmlXmlHeader = "\n" \
26 | "\n";
27 |
28 | class NoteFormatter
29 | {
30 | public:
31 | NoteFormatter(QString input_text);
32 |
33 | QString standardiseInput();
34 |
35 | QString convertFromEML();
36 | QString convertToEML();
37 |
38 | static QString createEmptyENML();
39 |
40 | private:
41 | QString inputText;
42 |
43 | QStringList invalidAttributes = { "id", "class", "onclick", "ondblclick", //"on*",
44 | "accesskey", "data", "dynsrc", "tabindex" };
45 | QStringList validCryptAttributes = { "cipher", "hint", "length" };
46 | QStringList validMediaAttributes = { "align", "hash", "style", "type" };
47 |
48 | QStringList validTags = { "en-note", "en-todo", "en-media", "en-crypt",
49 | //
50 | "a", "abbr", "acronym", "address", "area",
51 | "b", "bdo", "big", "blockquote", "br", "caption",
52 | "center", "cite", "code", "col", "colgroup", "dd",
53 | "del", "dfn", "div", "dl", "dt", "em", "font", "h1",
54 | "h2", "h3", "h4", "h5", "h6", "hr", "i", "img", "ins",
55 | "kbd", "li", "map", "ol", "p", "pre", "q", "s", "samp",
56 | "small", "span", "strike", "strong", "sub", "sup", "table",
57 | "tbody", "td", "tfoot", "th", "thead", "title", "tr", "tt",
58 | "u", "ul", "var", "xmp" };
59 | };
60 |
61 | #endif // NOTEFORMATTER_H
62 |
--------------------------------------------------------------------------------
/src/note_sync_controller.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef NOTESYNCCONTROLLER_H
19 | #define NOTESYNCCONTROLLER_H
20 |
21 | #include
22 |
23 | #include
24 |
25 |
26 | struct GuidMap{
27 | qevercloud::Guid local_guid;
28 | qevercloud::Guid official_guid;
29 | };
30 |
31 | typedef enum tAuthState {
32 | UNAUTHORISED,
33 | AUTHORISED
34 | } tAuthState;
35 |
36 | class NoteSyncController : public QObject
37 | {
38 | Q_OBJECT
39 |
40 | public:
41 | NoteSyncController(QString authToken, qevercloud::Guid notebookGuid, QString notestoreUrl);
42 |
43 | static tAuthState login();
44 |
45 | std::vector syncChanges();
46 | bool syncFromServer();
47 |
48 | signals:
49 | void authInvalid();
50 |
51 | private:
52 | qevercloud::Guid notebookGuid;
53 | qevercloud::NoteStore* noteStore;
54 |
55 | static qevercloud::Guid createOrGetNotebookGUID(QString authToken, QString notestoreUrl);
56 |
57 | qevercloud::Guid syncCreateNote(Note note);
58 | void syncDeleteNote(Note note);
59 | void syncUpdateNote(Note note);
60 | };
61 |
62 | #endif // NOTESYNCCONTROLLER_H
63 |
--------------------------------------------------------------------------------
/src/qevercloud/AsyncResult.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #include
10 | #include
11 | #include "http.h"
12 | #include
13 | #include
14 | #include
15 |
16 | namespace qevercloud {
17 |
18 | class AsyncResultPrivate
19 | {
20 | public:
21 | explicit AsyncResultPrivate(QString url, QByteArray postData, AsyncResult::ReadFunctionType readFunction,
22 | bool autoDelete, AsyncResult * q);
23 |
24 | explicit AsyncResultPrivate(QNetworkRequest request, QByteArray postData, AsyncResult::ReadFunctionType readFunction,
25 | bool autoDelete, AsyncResult * q);
26 |
27 | virtual ~AsyncResultPrivate();
28 |
29 | QNetworkRequest m_request;
30 | QByteArray m_postData;
31 | AsyncResult::ReadFunctionType m_readFunction;
32 | bool m_autoDelete;
33 |
34 | private:
35 | AsyncResult * const q_ptr;
36 | Q_DECLARE_PUBLIC(AsyncResult)
37 | };
38 |
39 | AsyncResultPrivate::AsyncResultPrivate(QString url, QByteArray postData, AsyncResult::ReadFunctionType readFunction,
40 | bool autoDelete, AsyncResult * q) :
41 | m_request(createEvernoteRequest(url)),
42 | m_postData(postData),
43 | m_readFunction(readFunction),
44 | m_autoDelete(autoDelete),
45 | q_ptr(q)
46 | {}
47 |
48 | AsyncResultPrivate::AsyncResultPrivate(QNetworkRequest request, QByteArray postData, AsyncResult::ReadFunctionType readFunction,
49 | bool autoDelete, AsyncResult * q) :
50 | m_request(request),
51 | m_postData(postData),
52 | m_readFunction(readFunction),
53 | m_autoDelete(autoDelete),
54 | q_ptr(q)
55 | {}
56 |
57 |
58 | AsyncResultPrivate::~AsyncResultPrivate()
59 | {}
60 |
61 | QVariant AsyncResult::asIs(QByteArray replyData)
62 | {
63 | return replyData;
64 | }
65 |
66 | AsyncResult::AsyncResult(QString url, QByteArray postData, AsyncResult::ReadFunctionType readFunction,
67 | bool autoDelete, QObject * parent) :
68 | QObject(parent),
69 | d_ptr(new AsyncResultPrivate(url, postData, readFunction, autoDelete, this))
70 | {
71 | QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
72 | }
73 |
74 | AsyncResult::AsyncResult(QNetworkRequest request, QByteArray postData, qevercloud::AsyncResult::ReadFunctionType readFunction,
75 | bool autoDelete, QObject * parent) :
76 | QObject(parent),
77 | d_ptr(new AsyncResultPrivate(request, postData, readFunction, autoDelete, this))
78 | {
79 | QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection);
80 | }
81 |
82 | AsyncResult::~AsyncResult()
83 | {
84 | delete d_ptr;
85 | }
86 |
87 | bool AsyncResult::waitForFinished(int timeout)
88 | {
89 | QEventLoop loop;
90 | QObject::connect(this, SIGNAL(finished(QVariant,QSharedPointer)), &loop, SLOT(quit()));
91 |
92 | if(timeout >= 0) {
93 | QTimer timer;
94 | EventLoopFinisher finisher(&loop, 1);
95 | connect(&timer, SIGNAL(timeout()), &finisher, SLOT(stopEventLoop()));
96 | timer.setSingleShot(true);
97 | timer.setInterval(timeout);
98 | timer.start();
99 | }
100 |
101 | bool res = (loop.exec(QEventLoop::ExcludeUserInputEvents) == 0);
102 | return res;
103 | }
104 |
105 | void AsyncResult::start()
106 | {
107 | Q_D(AsyncResult);
108 | ReplyFetcher * replyFetcher = new ReplyFetcher;
109 | QObject::connect(replyFetcher, QEC_SIGNAL(ReplyFetcher,replyFetched,QObject*),
110 | this, QEC_SLOT(AsyncResult,onReplyFetched,QObject*));
111 | replyFetcher->start(evernoteNetworkAccessManager(), d->m_request, d->m_postData);
112 | }
113 |
114 | void AsyncResult::onReplyFetched(QObject * rp)
115 | {
116 | Q_D(AsyncResult);
117 |
118 | ReplyFetcher * reply = qobject_cast(rp);
119 | QSharedPointer error;
120 | QVariant result;
121 |
122 | try
123 | {
124 | if (reply->isError()) {
125 | error = QSharedPointer(new EverCloudExceptionData(reply->errorText()));
126 | }
127 | else if(reply->httpStatusCode() != 200) {
128 | error = QSharedPointer(new EverCloudExceptionData(QStringLiteral("HTTP Status Code = %1").arg(reply->httpStatusCode())));
129 | }
130 | else {
131 | result = d->m_readFunction(reply->receivedData());
132 | }
133 | }
134 | catch(const EverCloudException & e) {
135 | error = e.exceptionData();
136 | }
137 | catch(const std::exception & e) {
138 | error = QSharedPointer(new EverCloudExceptionData(QStringLiteral("Exception of type \"%1\" with the message: %2")
139 | .arg(QString::fromUtf8(typeid(e).name()), QString::fromUtf8(e.what()))));
140 | }
141 | catch(...) {
142 | error = QSharedPointer(new EverCloudExceptionData(QStringLiteral("Unknown exception")));
143 | }
144 |
145 | emit finished(result, error);
146 | reply->deleteLater();
147 |
148 | if (d->m_autoDelete) {
149 | this->deleteLater();
150 | }
151 | }
152 |
153 | } // namespace qevercloud
154 |
--------------------------------------------------------------------------------
/src/qevercloud/AsyncResult.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_ASYNC_RESULT_H
10 | #define QEVERCLOUD_ASYNC_RESULT_H
11 |
12 | #include "qt4helpers.h"
13 | #include "export.h"
14 | #include "EverCloudException.h"
15 | #include
16 | #include
17 |
18 | namespace qevercloud {
19 |
20 | QT_FORWARD_DECLARE_CLASS(AsyncResultPrivate)
21 |
22 | /**
23 | * @brief Returned by asynchonous versions of functions.
24 | *
25 | * Wait for AsyncResult::finished signal.
26 | *
27 | * Intended usage is something like this:
28 | *
29 | * @code
30 | NoteStore* ns;
31 | Note note;
32 | ...
33 | QObject::connect(ns->createNoteAsync(note), &AsyncResult::finished, [ns](QVariant result, QSharedPointer error) {
34 | if(!error.isNull()) {
35 | // do something in case of an error
36 | } else {
37 | Note note = result.value();
38 | // process returned result
39 | }
40 | });
41 | @endcode
42 | */
43 | class QEVERCLOUD_EXPORT AsyncResult: public QObject
44 | {
45 | Q_OBJECT
46 | Q_DISABLE_COPY(AsyncResult)
47 | private:
48 | static QVariant asIs(QByteArray replyData);
49 |
50 | public:
51 | typedef QVariant (*ReadFunctionType)(QByteArray replyData);
52 |
53 | AsyncResult(QString url, QByteArray postData, ReadFunctionType readFunction = AsyncResult::asIs,
54 | bool autoDelete = true, QObject * parent = Q_NULLPTR);
55 |
56 | AsyncResult(QNetworkRequest request, QByteArray postData, ReadFunctionType readFunction = AsyncResult::asIs,
57 | bool autoDelete = true, QObject * parent = Q_NULLPTR);
58 |
59 | ~AsyncResult();
60 |
61 | /**
62 | * @brief Wait for asyncronous operation to complete.
63 | * @param timeout
64 | * Maximum time to wait in milliseconds. Forever if < 0.
65 | * @return true if finished successfully, false in case of the timeout
66 | */
67 | bool waitForFinished(int timeout = -1);
68 |
69 | Q_SIGNALS:
70 | /**
71 | * @brief Emitted upon asyncronous call completition.
72 | * @param result
73 | * @param error
74 | * error.isNull() != true in case of an error. See EverCloudExceptionData for more details.
75 | *
76 | * AsyncResult deletes itself after emitting this signal. You don't have to manage it's lifetime explicitly.
77 | */
78 | void finished(QVariant result, QSharedPointer error);
79 |
80 | private Q_SLOTS:
81 | void onReplyFetched(QObject * rp);
82 | void start();
83 |
84 | private:
85 | AsyncResultPrivate * const d_ptr;
86 | Q_DECLARE_PRIVATE(AsyncResult)
87 | };
88 |
89 | } // namespace qevercloud
90 |
91 | #endif // QEVERCLOUD_ASYNC_RESULT_H
92 |
--------------------------------------------------------------------------------
/src/qevercloud/EventLoopFinisher.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #include
10 |
11 | namespace qevercloud {
12 |
13 | class EventLoopFinisherPrivate
14 | {
15 | public:
16 | EventLoopFinisherPrivate(QEventLoop * loop, int exitCode) :
17 | m_loop(loop),
18 | m_exitCode(exitCode)
19 | {}
20 |
21 | QEventLoop * m_loop;
22 | int m_exitCode;
23 | };
24 |
25 | qevercloud::EventLoopFinisher::EventLoopFinisher(QEventLoop * loop, int exitCode, QObject * parent) :
26 | QObject(parent),
27 | d_ptr(new EventLoopFinisherPrivate(loop, exitCode))
28 | {}
29 |
30 | EventLoopFinisher::~EventLoopFinisher()
31 | {
32 | delete d_ptr;
33 | }
34 |
35 | void qevercloud::EventLoopFinisher::stopEventLoop()
36 | {
37 | Q_D(EventLoopFinisher);
38 | d->m_loop->exit(d->m_exitCode);
39 | }
40 |
41 | } // namespace qevercloud
42 |
--------------------------------------------------------------------------------
/src/qevercloud/EventLoopFinisher.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_EVENT_LOOP_FINISHER_H
10 | #define QEVERCLOUD_EVENT_LOOP_FINISHER_H
11 |
12 | #include "qt4helpers.h"
13 | #include "export.h"
14 | #include
15 | #include
16 |
17 | namespace qevercloud {
18 |
19 | QT_FORWARD_DECLARE_CLASS(EventLoopFinisherPrivate)
20 |
21 | class QEVERCLOUD_EXPORT EventLoopFinisher: public QObject
22 | {
23 | Q_OBJECT
24 | public:
25 | explicit EventLoopFinisher(QEventLoop * loop, int exitCode, QObject * parent = Q_NULLPTR);
26 | ~EventLoopFinisher();
27 |
28 | public Q_SLOTS:
29 | void stopEventLoop();
30 |
31 | private:
32 | EventLoopFinisherPrivate * const d_ptr;
33 | Q_DECLARE_PRIVATE(EventLoopFinisher)
34 | };
35 |
36 | } // namespace qevercloud
37 |
38 | #endif // QEVERCLOUD_EVENT_LOOP_FINISHER_H
39 |
--------------------------------------------------------------------------------
/src/qevercloud/EverCloudException.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #include
10 |
11 | namespace qevercloud {
12 |
13 | EverCloudException::EverCloudException() :
14 | m_error()
15 | {}
16 |
17 | EverCloudException::EverCloudException(QString error) :
18 | m_error(error.toUtf8())
19 | {}
20 |
21 | EverCloudException::EverCloudException(const std::string & error) :
22 | m_error(error.c_str())
23 | {}
24 |
25 | EverCloudException::EverCloudException(const char * error) :
26 | m_error(error)
27 | {}
28 |
29 | EverCloudException::~EverCloudException() throw()
30 | {}
31 |
32 | const char * EverCloudException::what() const throw()
33 | {
34 | return m_error.constData();
35 | }
36 |
37 | QSharedPointer QEVERCLOUD_EXPORT EverCloudException::exceptionData() const
38 | {
39 | return QSharedPointer(new EverCloudExceptionData(QString::fromUtf8(what())));
40 | }
41 |
42 | EverCloudExceptionData::EverCloudExceptionData(QString error) :
43 | errorMessage(error)
44 | {}
45 |
46 | void EverCloudExceptionData::throwException() const
47 | {
48 | throw EverCloudException(errorMessage);
49 | }
50 |
51 | EvernoteException::EvernoteException() :
52 | EverCloudException()
53 | {}
54 |
55 | EvernoteException::EvernoteException(QString error) :
56 | EverCloudException(error)
57 | {}
58 |
59 | EvernoteException::EvernoteException(const std::string & error) :
60 | EverCloudException(error)
61 | {}
62 |
63 | EvernoteException::EvernoteException(const char * error) :
64 | EverCloudException(error)
65 | {}
66 |
67 | QSharedPointer EvernoteException::exceptionData() const
68 | {
69 | return QSharedPointer(new EvernoteExceptionData(QString::fromUtf8(what())));
70 | }
71 |
72 | EvernoteExceptionData::EvernoteExceptionData(QString error) :
73 | EverCloudExceptionData(error)
74 | {}
75 |
76 | void EvernoteExceptionData::throwException() const
77 | {
78 | throw EvernoteException(errorMessage);
79 | }
80 |
81 | } // namespace qevercloud
82 |
--------------------------------------------------------------------------------
/src/qevercloud/EverCloudException.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_EVER_CLOUD_EXCEPTION_H
10 | #define QEVERCLOUD_EVER_CLOUD_EXCEPTION_H
11 |
12 | #include "qt4helpers.h"
13 | #include "export.h"
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | namespace qevercloud {
20 |
21 | class QEVERCLOUD_EXPORT EverCloudExceptionData;
22 |
23 | /**
24 | * All exceptions throws by the library are of this class or its descendants.
25 | */
26 | class QEVERCLOUD_EXPORT EverCloudException: public std::exception
27 | {
28 | protected:
29 | mutable QByteArray m_error;
30 |
31 | public:
32 | explicit EverCloudException();
33 | explicit EverCloudException(QString error);
34 | explicit EverCloudException(const std::string & error);
35 | explicit EverCloudException(const char * error);
36 | ~EverCloudException() throw();
37 |
38 | const char * what() const throw();
39 |
40 | virtual QSharedPointer exceptionData() const;
41 | };
42 |
43 | /**
44 | * @brief EverCloudException counterpart for asynchronous API.
45 | *
46 | * Asynchronous functions cannot throw exceptions so descendants of EverCloudExceptionData are retunded instead
47 | * in case of an error. Every exception class has its own counterpart.
48 | * The EverCloudExceptionData descendants hierarchy is a copy of the EverCloudException descendants hierarchy.
49 | *
50 | * The main reason not to use exception classes directly is that dynamic_cast does not work across module (exe, dll, etc) boundaries
51 | * in general, while `qobject_cast` do work as expected. That's why I decided to inherit my error classes from QObject.
52 | *
53 | * In general error checking in asynchronous API look like this:
54 | *
55 | * @code
56 | NoteStore* ns;
57 | ...
58 | QObject::connect(ns->getNotebook(notebookGuid), &AsyncResult::finished, [](QVariant result, QSharedPointer error) {
59 | if(!error.isNull()) {
60 | QSharedPointer errorNotFound = error.objectCast();
61 | QSharedPointer errorUser = error.objectCast();
62 | QSharedPointer errorSystem = error.objectCast();
63 | if(!errorNotFound.isNull()) {
64 | qDebug() << "notebook not found" << errorNotFound.identifier << errorNotFound.key;
65 | } else if(!errorUser.isNull()) {
66 | qDebug() << errorUser.errorMessage;
67 | } else if(!errorSystem.isNull()) {
68 | if(errorSystem.errorCode == EDAMErrorCode::RATE_LIMIT_REACHED) {
69 | qDebug() << "Evernote API rate limits are reached";
70 | } else if(errorSystem.errorCode == EDAMErrorCode::AUTH_EXPIRED) {
71 | qDebug() << "Authorization token is inspired";
72 | } else {
73 | // some other Evernote trouble
74 | qDebug() << errorSystem.errorMessage;
75 | }
76 | } else {
77 | // some unexpected error
78 | qDebug() << error.errorMessage;
79 | }
80 | } else {
81 | // success
82 | }
83 | });
84 |
85 | @endcode
86 | */
87 | class QEVERCLOUD_EXPORT EverCloudExceptionData: public QObject
88 | {
89 | Q_OBJECT
90 | Q_DISABLE_COPY(EverCloudExceptionData)
91 | public:
92 | /**
93 | * Contains an error message. It's the std::exception::what() counterpart.
94 | */
95 | QString errorMessage;
96 |
97 | explicit EverCloudExceptionData(QString error);
98 |
99 | /**
100 | * If you want to throw an exception that corresponds to a recrived EverCloudExceptionData
101 | * descendant than call this function. Do not use `throw` statement, it's not polymorphic.
102 | */
103 | virtual void throwException() const;
104 | };
105 |
106 | /**
107 | * All exception sent by Evernote servers (as opposed to other error conditions, for example http errors) are
108 | * descendants of this class.
109 | */
110 | class QEVERCLOUD_EXPORT EvernoteException: public EverCloudException
111 | {
112 | public:
113 | explicit EvernoteException();
114 | explicit EvernoteException(QString error);
115 | explicit EvernoteException(const std::string & error);
116 | explicit EvernoteException(const char * error);
117 |
118 | virtual QSharedPointer exceptionData() const Q_DECL_OVERRIDE;
119 | };
120 |
121 | /** Asynchronous API conterpart of EvernoteException. See EverCloudExceptionData for more details.*/
122 | class QEVERCLOUD_EXPORT EvernoteExceptionData: public EverCloudExceptionData
123 | {
124 | Q_OBJECT
125 | Q_DISABLE_COPY(EvernoteExceptionData)
126 | public:
127 | explicit EvernoteExceptionData(QString error);
128 | virtual void throwException() const Q_DECL_OVERRIDE;
129 | };
130 |
131 | } // namespace qevercloud
132 |
133 | #endif // QEVERCLOUD_EVER_CLOUD_EXCEPTION_H
134 |
--------------------------------------------------------------------------------
/src/qevercloud/InkNoteImageDownloader.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2016 Dmitry Ivanov
3 | *
4 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | #include
9 | #include
10 | #include "http.h"
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | namespace qevercloud {
17 |
18 | class InkNoteImageDownloaderPrivate
19 | {
20 | public:
21 | QPair createPostRequest(const QString & urlPart,
22 | const int sliceNumber, const bool isPublic = false);
23 |
24 | QString m_host;
25 | QString m_shardId;
26 | QString m_authenticationToken;
27 | int m_width;
28 | int m_height;
29 | };
30 |
31 | InkNoteImageDownloader::InkNoteImageDownloader() :
32 | d_ptr(new InkNoteImageDownloaderPrivate)
33 | {}
34 |
35 | InkNoteImageDownloader::InkNoteImageDownloader(QString host, QString shardId, QString authenticationToken,
36 | int width, int height) :
37 | d_ptr(new InkNoteImageDownloaderPrivate)
38 | {
39 | d_ptr->m_host = host;
40 | d_ptr->m_shardId = shardId;
41 | d_ptr->m_authenticationToken = authenticationToken;
42 | d_ptr->m_width = width;
43 | d_ptr->m_height = height;
44 | }
45 |
46 | InkNoteImageDownloader::~InkNoteImageDownloader()
47 | {
48 | delete d_ptr;
49 | }
50 |
51 | InkNoteImageDownloader & InkNoteImageDownloader::setHost(QString host)
52 | {
53 | d_ptr->m_host = host;
54 | return *this;
55 | }
56 |
57 | InkNoteImageDownloader & InkNoteImageDownloader::setShardId(QString shardId)
58 | {
59 | d_ptr->m_shardId = shardId;
60 | return *this;
61 | }
62 |
63 | InkNoteImageDownloader & InkNoteImageDownloader::setAuthenticationToken(QString authenticationToken)
64 | {
65 | d_ptr->m_authenticationToken = authenticationToken;
66 | return *this;
67 | }
68 |
69 | InkNoteImageDownloader & InkNoteImageDownloader::setWidth(int width)
70 | {
71 | d_ptr->m_width = width;
72 | return *this;
73 | }
74 |
75 | InkNoteImageDownloader & InkNoteImageDownloader::setHeight(int height)
76 | {
77 | d_ptr->m_height = height;
78 | return *this;
79 | }
80 |
81 | QByteArray InkNoteImageDownloader::download(Guid guid, bool isPublic)
82 | {
83 | Q_D(InkNoteImageDownloader);
84 |
85 | QSize size(d_ptr->m_width, d_ptr->m_height);
86 | QImage inkNoteImage(size, QImage::Format_RGB32);
87 |
88 | QString urlPattern = QStringLiteral("https://%1/shard/%2/res/%3.ink?slice=");
89 | QString urlPart = urlPattern.arg(d->m_host, d->m_shardId, guid);
90 |
91 | int painterPosition = 0;
92 | int sliceCounter = 1;
93 | while(true)
94 | {
95 | int httpStatusCode = 0;
96 | QPair postRequest = d->createPostRequest(urlPart, sliceCounter, isPublic);
97 |
98 | QByteArray reply = simpleDownload(evernoteNetworkAccessManager(), postRequest.first,
99 | postRequest.second, &httpStatusCode);
100 | if (httpStatusCode != 200) {
101 | throw EverCloudException(QStringLiteral("HTTP Status Code = %1").arg(httpStatusCode));
102 | }
103 |
104 | QImage replyImagePart;
105 | Q_UNUSED(replyImagePart.loadFromData(reply, "PNG"))
106 | if (replyImagePart.isNull())
107 | {
108 | if (Q_UNLIKELY(inkNoteImage.isNull())) {
109 | throw EverCloudException(QStringLiteral("Ink note's image part is null before even starting to assemble"));
110 | }
111 |
112 | break;
113 | }
114 |
115 | if (replyImagePart.format() != inkNoteImage.format()) {
116 | inkNoteImage = inkNoteImage.convertToFormat(replyImagePart.format());
117 | }
118 |
119 | QRect painterCurrentRect(0, painterPosition, replyImagePart.width(), replyImagePart.height());
120 | painterPosition += replyImagePart.height();
121 |
122 | QPainter painter(&inkNoteImage);
123 | painter.setRenderHints(QPainter::Antialiasing);
124 | painter.drawImage(painterCurrentRect, replyImagePart);
125 |
126 | if (painterPosition >= size.height()) {
127 | break;
128 | }
129 | }
130 |
131 | if (inkNoteImage.isNull()) {
132 | return QByteArray();
133 | }
134 |
135 | QByteArray imageData;
136 | QBuffer buffer(&imageData);
137 | Q_UNUSED(buffer.open(QIODevice::WriteOnly))
138 | inkNoteImage.save(&buffer, "PNG");
139 | return imageData;
140 | }
141 |
142 | QPair InkNoteImageDownloaderPrivate::createPostRequest(const QString & urlPart,
143 | const int sliceNumber,
144 | const bool isPublic)
145 | {
146 | QNetworkRequest request;
147 | request.setUrl(QUrl(urlPart + QString::number(sliceNumber)));
148 | request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
149 |
150 | QByteArray postData = ""; // not QByteArray()! or else ReplyFetcher will not work.
151 | if (!isPublic) {
152 | postData = QByteArray("auth=")+ QUrl::toPercentEncoding(m_authenticationToken);
153 | }
154 |
155 | return qMakePair(request, postData);
156 | }
157 |
158 | } // namespace qevercloud
159 |
--------------------------------------------------------------------------------
/src/qevercloud/InkNoteImageDownloader.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2016 Dmitry Ivanov
3 | *
4 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
5 | * https://opensource.org/licenses/MIT
6 | */
7 |
8 | #ifndef QEVERCLOD_INK_NOTE_IMAGE_DOWNLOADER_H
9 | #define QEVERCLOD_INK_NOTE_IMAGE_DOWNLOADER_H
10 |
11 | #include "export.h"
12 | #include "AsyncResult.h"
13 | #include "generated/types.h"
14 | #include
15 | #include
16 | #include
17 |
18 | namespace qevercloud {
19 |
20 | /** @cond HIDDEN_SYMBOLS */
21 | class InkNoteImageDownloaderPrivate;
22 | /** @endcond */
23 |
24 | /**
25 | * @brief the class is for downloading the images of ink notes which can be created
26 | * with the official Evernote client on Windows (only with it, at least at the time
27 | * of this writing).
28 | *
29 | * On all other platforms the most one can get instead of the actual ink note
30 | * is its non-editable image. This class retrieves just these, exclusively in PNG format.
31 | *
32 | * NOTE: almost the entirety of this class' content represents an ad-hoc solution
33 | * to a completely undocumented feature of Evernote service. A very small glimpse
34 | * of information can be found e.g. here
35 | * but it is practically all one can find.
36 | */
37 | class QEVERCLOUD_EXPORT InkNoteImageDownloader
38 | {
39 | public:
40 | /**
41 | * @brief Default constructor.
42 | *
43 | * host, shardId, authenticationToken, width, height have to be specified before calling
44 | * @link download @endlink or @link createPostRequest @endlink
45 | */
46 | InkNoteImageDownloader();
47 |
48 | /**
49 | * @brief Constructs InkNoteImageDownloader.
50 | * @param host
51 | * www.evernote.com or sandbox.evernote.com
52 | * @param shardId
53 | * You can get the value from UserStore service or as a result of an authentication.
54 | * @param authenticationToken
55 | * For working private ink notes you must supply a valid authentication token.
56 | * For public resources the value specified is not used.
57 | * @param width
58 | * Width of the ink note's resource
59 | * @param height
60 | * Height of the ink note's resource
61 | */
62 | InkNoteImageDownloader(QString host, QString shardId, QString authenticationToken, int width, int height);
63 |
64 | virtual ~InkNoteImageDownloader();
65 |
66 | /**
67 | * @param host
68 | * www.evernote.com or sandbox.evernote.com
69 | */
70 | InkNoteImageDownloader & setHost(QString host);
71 |
72 | /**
73 | * @param shardId
74 | * You can get the value from UserStore service or as a result of an authentication.
75 | */
76 | InkNoteImageDownloader & setShardId(QString shardId);
77 |
78 | /**
79 | * @param authenticationToken
80 | * For working private ink notes you must supply a valid authentication token.
81 | * For public resources the value specified is not used.
82 | */
83 | InkNoteImageDownloader & setAuthenticationToken(QString authenticationToken);
84 |
85 | /**
86 | * @param width
87 | * Width of the ink note's resource
88 | */
89 | InkNoteImageDownloader & setWidth(int width);
90 |
91 | /**
92 | * @param height
93 | * Height of the ink note's resource
94 | */
95 | InkNoteImageDownloader & setHeight(int height);
96 |
97 | /**
98 | * @brief Downloads the image for the ink note.
99 | *
100 | * Unlike other pieces of QEverCloud API, downloading of ink note images is currently
101 | * synchronous only. The reason for that is that AsyncResult is bounded to a single
102 | * QNetworkRequest object but downloading of the ink note image might take multiple
103 | * requests for several ink note image's vertical stripes which are then merged
104 | * together to form a single image. Downloading the entire ink note's image
105 | * via a single request works sometimes but sometimes Evernote replies to such request
106 | * with messed up data which cannot be loaded into a QImage. The reason for that behaviour
107 | * is unknown at the moment, and, given the state of official documentation - missing -
108 | * it is likely to stay so. if someone has an idea how to make it more reliable,
109 | * please let me know.
110 | *
111 | * @param guid
112 | * The guid of the ink note's resource
113 | * @param isPublic
114 | * Specify true for public ink notes. In this case authentication token is not sent to
115 | * with the request as it shoud be according to the docs.
116 | * @return downloaded data.
117 | *
118 | */
119 | QByteArray download(Guid guid, bool isPublic = false);
120 |
121 | private:
122 | InkNoteImageDownloaderPrivate * const d_ptr;
123 | Q_DECLARE_PRIVATE(InkNoteImageDownloader)
124 | };
125 |
126 | } // namespace qevercloud
127 |
128 | #endif // QEVERCLOD_INK_NOTE_IMAGE_DOWNLOADER_H
129 |
--------------------------------------------------------------------------------
/src/qevercloud/Optional.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_OPTIONAL_H
10 | #define QEVERCLOUD_OPTIONAL_H
11 |
12 | #include "EverCloudException.h"
13 | #include
14 |
15 | namespace qevercloud {
16 |
17 | /**
18 | * Supports optional values.
19 | *
20 | * Most of the fields in the Evernote API structs are optional. But C++ does not support this notion directly.
21 | *
22 | * To implement the concept of optional values conventional Thrift C++ wrapper uses a special field of a struct type
23 | * where each field is of type bool with the same name as a field in the struct. This bool flag indicated was
24 | * the field with the same name in the outer struct assigned or not.
25 | *
26 | * While this method have its advantages (obviousness and simplicity) I found it very inconvenient to work with.
27 | * You have to check by hand that both values (value itself and its __isset flag) are in sync.
28 | * There is no checks whatsoever against an error and such an error is too easy to make.
29 | *
30 | * So for my library I created a special class that supports the optional value notion explicitly.
31 | * Basically Optional class just holds a bool value that tracks the fact that a value was assigned. But this tracking
32 | * is done automatically and attempts to use unissigned values throw exceptions. In this way errors are much harder to
33 | * make and it's harder for them to slip through testing unnoticed too.
34 | *
35 | */
36 | template
37 | class Optional
38 | {
39 | public:
40 | /** Default constructor.
41 | * Default Optional is not set.
42 | */
43 | Optional() :
44 | m_isSet(false),
45 | m_value(T())
46 | {}
47 |
48 | /**
49 | * Copy constructor.
50 | */
51 | Optional(const Optional & o) :
52 | m_isSet(o.m_isSet),
53 | m_value(o.m_value)
54 | {}
55 |
56 | /**
57 | * Template copy constructor. Allows to be initialized with Optional of any compatible type.
58 | */
59 | template
60 | Optional(const Optional & o) :
61 | m_isSet(o.m_isSet),
62 | m_value(o.m_value)
63 | {}
64 |
65 | /**
66 | * Initialization with a value of the type T. Note: it's implicit.
67 | */
68 | Optional(const T & value) :
69 | m_isSet(true),
70 | m_value(value)
71 | {}
72 |
73 | /**
74 | * Template initialization with a value of any compatible type.
75 | */
76 | template
77 | Optional(const X & value) :
78 | m_isSet(true),
79 | m_value(value)
80 | {}
81 |
82 | /**
83 | * Assignment.
84 | */
85 | Optional & operator=(const Optional & o)
86 | {
87 | m_value = o.m_value;
88 | m_isSet = o.m_isSet;
89 | return *this;
90 | }
91 |
92 | /**
93 | * Template assignment with an Optional of any compatible value.
94 | */
95 | template
96 | Optional & operator=(const Optional & o)
97 | {
98 | m_value = o.m_value;
99 | m_isSet = o.m_isSet;
100 | return *this;
101 | }
102 |
103 | /**
104 | * Assignment with a value of the type T.
105 | */
106 | Optional & operator=(const T & value)
107 | {
108 | m_value = value;
109 | m_isSet = true;
110 | return *this;
111 | }
112 |
113 | /**
114 | * Template assignment with a value of any compatible type.
115 | */
116 | template
117 | Optional & operator=(const X & value)
118 | {
119 | m_value = value;
120 | m_isSet = true;
121 | return *this;
122 | }
123 |
124 | /**
125 | * Implicit conversion of Optional to T.
126 | *
127 | * const version.
128 | */
129 | operator const T&() const
130 | {
131 | if (!m_isSet) {
132 | throw EverCloudException("qevercloud::Optional: nonexistent value access");
133 | }
134 |
135 | return m_value;
136 | }
137 |
138 | /**
139 | * Implicit conversion of Optional to T.
140 | *
141 | * Note: a reference is returned, not a copy.
142 | */
143 | operator T&()
144 | {
145 | if (!m_isSet) {
146 | throw EverCloudException("qevercloud::Optional: nonexistent value access");
147 | }
148 |
149 | return m_value;
150 | }
151 |
152 | /**
153 | * Returs a reference to the holded value.
154 | *
155 | * const version.
156 | *
157 | */
158 | const T & ref() const
159 | {
160 | if (!m_isSet) {
161 | throw EverCloudException("qevercloud::Optional: nonexistent value access");
162 | }
163 |
164 | return m_value;
165 | }
166 |
167 | /**
168 | * Returs reference to the holded value.
169 | *
170 | * There are contexts in C++ where impicit type conversions can't help. For example:
171 | *
172 | * @code
173 | Optional l;
174 | for(auto s : l); // you will hear from your compiler
175 | @endcode
176 | *
177 | * Explicit type conversion can be used...
178 | *
179 | * @code
180 | Optional l;
181 | for(auto s : static_cast(l)); // ugh...
182 | @endcode
183 | *
184 | * ... but this is indeed ugly as hell.
185 | *
186 | * So I implemented ref() function that returns a reference to the holded value.
187 | * @code
188 | Optional l;
189 | for(auto s : l.ref()); // not ideal but OK
190 | @endcode
191 | */
192 | T & ref()
193 | {
194 | if (!m_isSet) {
195 | throw EverCloudException("qevercloud::Optional: nonexistent value access");
196 | }
197 |
198 | return m_value;
199 | }
200 |
201 | /**
202 | * @brief Checks if value is set.
203 | * @return true if Optional have been assigned a value and false otherwise.
204 | *
205 | * Access to an unassigned ("not set") Optional lead to an exception.
206 | */
207 | bool isSet() const
208 | {
209 | return m_isSet;
210 | }
211 |
212 | /**
213 | * Clears an Optional.
214 | *
215 | * @code
216 |
217 | Optional o(1);
218 | o.clear();
219 | cout << o; // exception
220 |
221 | @endcode
222 | */
223 | void clear()
224 | {
225 | m_isSet = false;
226 | m_value = T();
227 | }
228 |
229 | /**
230 | * Fast way to initialize an Optional with a default value.
231 | *
232 | * It's very useful for structs.
233 | *
234 | * @code
235 |
236 | struct S2 {int f;};
237 | struct S {int f1; Optional f2};
238 | Optional o; // o.isSet() != ture
239 |
240 | // without init() it's cumbersome to access struct fields
241 | // it's especially true for nested Optionals
242 | o = S(); // now o is set
243 | o->f2 = S2(); // and o.f2 is set
244 | o->f2->f = 1; // so at last it can be used
245 |
246 | // with init() it's simpler
247 | o.init()->f2.init()->f = 1;
248 |
249 | @endcode
250 | * @return reference to itself
251 | */
252 | Optional & init()
253 | {
254 | m_isSet = true;
255 | m_value = T();
256 | return *this;
257 | }
258 |
259 | /**
260 | * Two syntatic constructs come to mind to use for implementation of access to a struct's/class's field directly from Optional.
261 | *
262 | * One is the dereference operator.
263 | * This is what boost::optional uses. While it's conceptually nice
264 | * I found it to be not a very convenient way to refer to structs, especially nested ones.
265 | * So I overloaded the operator-> and use smart pointer semantics.
266 | *
267 | * @code
268 | struct S1 {int f1;};
269 | struct S2 {Optional f2;};
270 | Optional o;
271 |
272 | *((*o).f2).f1; // boost way, not implemented
273 |
274 | o->f2->f1; // QEverCloud way
275 |
276 | @endcode
277 | *
278 | * I admit, boost::optional is much more elegant overall. It uses pointer semantics quite clearly and
279 | * in an instantly understandable way. It's universal (* works for any type and not just structs). There is
280 | * no need for implicit type concersions and so there is no subtleties because of it. And so on.
281 | *
282 | * But then referring to struct fields is a chore. And this is the most common use case of Optionals in QEverCloud.
283 | *
284 | * So I decided to use non-obvious-on-the-first-sight semantics for my Optional. IMO it's much more convenient when gotten used to.
285 | *
286 | */
287 | T * operator->()
288 | {
289 | if (!m_isSet) {
290 | throw EverCloudException("qevercloud::Optional: nonexistent value access");
291 | }
292 |
293 | return &m_value;
294 | }
295 |
296 | /**
297 | * const version.
298 | */
299 | const T * operator->() const
300 | {
301 | if (!m_isSet) {
302 | throw EverCloudException("qevercloud::Optional: nonexistent value access");
303 | }
304 |
305 | return &m_value;
306 | }
307 |
308 | /**
309 | * The function is sometimes useful to simplify checking for the value being set.
310 | * @param defaultValue
311 | * The value to return if Optional is not set.
312 | * @return Optional value if set and defaultValue otherwise.
313 | */
314 | T value(T defaultValue = T()) const
315 | {
316 | return m_isSet ? m_value : defaultValue;
317 | }
318 |
319 | /**
320 | * Two optionals are equal if they are both not set or have
321 | * equal values.
322 | *
323 | * I do not define `operator==` due to not easily resolvable conflicts with `operator T&`.
324 | *
325 | * Note that `optional == other_optional` may throw but `optional.isEqual(other_optional)` will not.
326 | */
327 | bool isEqual(const Optional & other) const
328 | {
329 | if(m_isSet != other.m_isSet) return false;
330 | return !m_isSet || (m_value == other.m_value);
331 | }
332 |
333 | template friend class Optional;
334 |
335 | friend void swap(Optional & first, Optional & second)
336 | {
337 | using std::swap;
338 | swap(first.m_isSet, second.m_isSet);
339 | swap(first.m_value, second.m_value);
340 | }
341 |
342 | // Visual C++ does not to generate implicit move constructors so this stuff doesn't work with even recent MSVC compilers
343 | #if defined(Q_COMPILER_RVALUE_REFS) && !defined(_MSC_VER)
344 | Optional(Optional && other)
345 | {
346 | swap(*this, other);
347 | }
348 |
349 | Optional & operator=(Optional && other)
350 | {
351 | swap(*this, other);
352 | return *this;
353 | }
354 |
355 | Optional(T && other)
356 | {
357 | using std::swap;
358 | m_isSet = true;
359 | swap(m_value, other);
360 | }
361 |
362 | Optional & operator=(T && other)
363 | {
364 | using std::swap;
365 | m_isSet = true;
366 | swap(m_value, other);
367 | return *this;
368 | }
369 | #endif
370 |
371 | private:
372 | bool m_isSet;
373 | T m_value;
374 | };
375 |
376 | } // namespace qevercloud
377 |
378 | #endif // QEVERCLOUD_OPTIONAL_H
379 |
--------------------------------------------------------------------------------
/src/qevercloud/QEverCloud.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_INFTHEADER_H
10 | #define QEVERCLOUD_INFTHEADER_H
11 |
12 | #include "AsyncResult.h"
13 | #include "EventLoopFinisher.h"
14 | #include "EverCloudException.h"
15 | #include "exceptions.h"
16 | #include "export.h"
17 | #include "globals.h"
18 | #include "Optional.h"
19 | #include "qt4helpers.h"
20 | #include "thumbnail.h"
21 | #include "InkNoteImageDownloader.h"
22 | //#include "VersionInfo.h"
23 | #include "generated/EDAMErrorCode.h"
24 | #include "generated/constants.h"
25 | #include "generated/services.h"
26 | #include "generated/types.h"
27 |
28 | #endif // QEVERCLOUD_INFTHEADER_H
29 |
--------------------------------------------------------------------------------
/src/qevercloud/QEverCloudOAuth.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUDOAUTH_INFTHEADER_H
10 | #define QEVERCLOUDOAUTH_INFTHEADER_H
11 |
12 | #include "QEverCloud.h"
13 | #include "oauth.h"
14 |
15 | #endif // QEVERCLOUDOAUTH_INFTHEADER_H
16 |
--------------------------------------------------------------------------------
/src/qevercloud/exceptions.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_EXCEPTIONS_H
10 | #define QEVERCLOUD_EXCEPTIONS_H
11 |
12 | #include "Optional.h"
13 | #include "export.h"
14 | #include "EverCloudException.h"
15 | #include "generated/EDAMErrorCode.h"
16 | #include "generated/types.h"
17 | #include
18 | #include
19 | #include
20 |
21 | namespace qevercloud {
22 |
23 | /**
24 | * Errors of the Thrift protocol level. It could be wrongly formatted parameters
25 | * or return values for example.
26 | */
27 | class QEVERCLOUD_EXPORT ThriftException: public EverCloudException
28 | {
29 | public:
30 | struct Type {
31 | enum type {
32 | UNKNOWN = 0,
33 | UNKNOWN_METHOD = 1,
34 | INVALID_MESSAGE_TYPE = 2,
35 | WRONG_METHOD_NAME = 3,
36 | BAD_SEQUENCE_ID = 4,
37 | MISSING_RESULT = 5,
38 | INTERNAL_ERROR = 6,
39 | PROTOCOL_ERROR = 7,
40 | INVALID_DATA = 8
41 | };
42 | };
43 |
44 | ThriftException();
45 | ThriftException(Type::type type);
46 | ThriftException(Type::type type, QString message);
47 |
48 | Type::type type() const;
49 |
50 | const char * what() const throw() Q_DECL_OVERRIDE;
51 |
52 | virtual QSharedPointer exceptionData() const Q_DECL_OVERRIDE;
53 |
54 | protected:
55 | Type::type m_type;
56 | };
57 |
58 | /** Asynchronous API conterpart of ThriftException. See EverCloudExceptionData for more details.*/
59 | class QEVERCLOUD_EXPORT ThriftExceptionData: public EverCloudExceptionData
60 | {
61 | Q_OBJECT
62 | Q_DISABLE_COPY(ThriftExceptionData)
63 | public:
64 | explicit ThriftExceptionData(QString error, ThriftException::Type::type type);
65 | virtual void throwException() const Q_DECL_OVERRIDE;
66 |
67 | protected:
68 | ThriftException::Type::type m_type;
69 | };
70 |
71 | inline QSharedPointer ThriftException::exceptionData() const
72 | {
73 | return QSharedPointer(new ThriftExceptionData(QString::fromUtf8(what()), type()));
74 | }
75 |
76 | /** Asynchronous API conterpart of EDAMUserException. See EverCloudExceptionData for more details.*/
77 | class QEVERCLOUD_EXPORT EDAMUserExceptionData: public EvernoteExceptionData
78 | {
79 | Q_OBJECT
80 | Q_DISABLE_COPY(EDAMUserExceptionData)
81 | public:
82 | explicit EDAMUserExceptionData(QString error, EDAMErrorCode::type errorCode, Optional parameter);
83 | virtual void throwException() const Q_DECL_OVERRIDE;
84 |
85 | protected:
86 | EDAMErrorCode::type m_errorCode;
87 | Optional m_parameter;
88 | };
89 |
90 | /** Asynchronous API conterpart of EDAMSystemException. See EverCloudExceptionData for more details.*/
91 | class QEVERCLOUD_EXPORT EDAMSystemExceptionData: public EvernoteExceptionData
92 | {
93 | Q_OBJECT
94 | Q_DISABLE_COPY(EDAMSystemExceptionData)
95 | public:
96 | explicit EDAMSystemExceptionData(QString err, EDAMErrorCode::type errorCode, Optional message, Optional rateLimitDuration);
97 | virtual void throwException() const Q_DECL_OVERRIDE;
98 |
99 | protected:
100 | EDAMErrorCode::type m_errorCode;
101 | Optional m_message;
102 | Optional m_rateLimitDuration;
103 | };
104 |
105 | /** Asynchronous API conterpart of EDAMNotFoundException. See EverCloudExceptionData for more details.*/
106 | class QEVERCLOUD_EXPORT EDAMNotFoundExceptionData: public EvernoteExceptionData
107 | {
108 | Q_OBJECT
109 | Q_DISABLE_COPY(EDAMNotFoundExceptionData)
110 | public:
111 | explicit EDAMNotFoundExceptionData(QString error, Optional identifier, Optional key);
112 | virtual void throwException() const Q_DECL_OVERRIDE;
113 |
114 | protected:
115 | Optional m_identifier;
116 | Optional m_key;
117 | };
118 |
119 | /** Asynchronous API conterpart of EDAMInvalidContactsException. See EverCloudExceptionData for more details.*/
120 | class QEVERCLOUD_EXPORT EDAMInvalidContactsExceptionData: public EvernoteExceptionData
121 | {
122 | Q_OBJECT
123 | Q_DISABLE_COPY(EDAMInvalidContactsExceptionData)
124 | public:
125 | explicit EDAMInvalidContactsExceptionData(QList contacts, Optional parameter, Optional > reasons);
126 | virtual void throwException() const Q_DECL_OVERRIDE;
127 |
128 | protected:
129 | QList< Contact > m_contacts;
130 | Optional< QString > m_parameter;
131 | Optional< QList< EDAMInvalidContactReason::type > > m_reasons;
132 | };
133 |
134 | /**
135 | * EDAMSystemException for `errorCode = RATE_LIMIT_REACHED`
136 | */
137 | class QEVERCLOUD_EXPORT EDAMSystemExceptionRateLimitReached: public EDAMSystemException
138 | {
139 | public:
140 | virtual QSharedPointer exceptionData() const Q_DECL_OVERRIDE;
141 | };
142 |
143 | /** Asynchronous API conterpart of EDAMSystemExceptionRateLimitReached. See EverCloudExceptionData for more details.*/
144 | class QEVERCLOUD_EXPORT EDAMSystemExceptionRateLimitReachedData: public EDAMSystemExceptionData
145 | {
146 | Q_OBJECT
147 | Q_DISABLE_COPY(EDAMSystemExceptionRateLimitReachedData)
148 | public:
149 | explicit EDAMSystemExceptionRateLimitReachedData(QString error, EDAMErrorCode::type errorCode, Optional message,
150 | Optional rateLimitDuration);
151 | virtual void throwException() const Q_DECL_OVERRIDE;
152 | };
153 |
154 | /**
155 | * EDAMSystemException for `errorCode = AUTH_EXPIRED`
156 | */
157 | class QEVERCLOUD_EXPORT EDAMSystemExceptionAuthExpired: public EDAMSystemException
158 | {
159 | public:
160 | virtual QSharedPointer exceptionData() const Q_DECL_OVERRIDE;
161 | };
162 |
163 | /** Asynchronous API conterpart of EDAMSystemExceptionAuthExpired. See EverCloudExceptionData for more details.*/
164 | class QEVERCLOUD_EXPORT EDAMSystemExceptionAuthExpiredData: public EDAMSystemExceptionData
165 | {
166 | Q_OBJECT
167 | Q_DISABLE_COPY(EDAMSystemExceptionAuthExpiredData)
168 | public:
169 | explicit EDAMSystemExceptionAuthExpiredData(QString error, EDAMErrorCode::type errorCode, Optional message,
170 | Optional rateLimitDuration);
171 | virtual void throwException() const Q_DECL_OVERRIDE;
172 | };
173 |
174 | } // namespace qevercloud
175 |
176 | #endif // QEVERCLOUD_EXCEPTIONS_H
177 |
--------------------------------------------------------------------------------
/src/qevercloud/export.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2017 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_EXPORT_H
10 | #define QEVERCLOUD_EXPORT_H
11 |
12 | #include
13 |
14 | #if defined(QEVERCLOUD_SHARED_LIBRARY)
15 | # define QEVERCLOUD_EXPORT Q_DECL_EXPORT
16 | #elif defined(QEVERCLOUD_STATIC_LIBRARY)
17 | # define QEVERCLOUD_EXPORT Q_DECL_EXPORT
18 | #else
19 | # define QEVERCLOUD_EXPORT Q_DECL_IMPORT
20 | #endif
21 |
22 | #endif // QEVERCLOUD_EXPORT_H
23 |
--------------------------------------------------------------------------------
/src/qevercloud/generated/EDAMErrorCode.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | *
8 | * This file was generated from Evernote Thrift API
9 | */
10 |
11 |
12 | #ifndef QEVERCLOUD_GENERATED_EDAMERRORCODE_H
13 | #define QEVERCLOUD_GENERATED_EDAMERRORCODE_H
14 |
15 | #include "../export.h"
16 |
17 | namespace qevercloud {
18 |
19 | /**
20 | * Numeric codes indicating the type of error that occurred on the
21 | * service.
22 | *
23 | *
UNKNOWN
24 | *
No information available about the error
25 | *
BAD_DATA_FORMAT
26 | *
The format of the request data was incorrect
27 | *
PERMISSION_DENIED
28 | *
Not permitted to perform action
29 | *
INTERNAL_ERROR
30 | *
Unexpected problem with the service
31 | *
DATA_REQUIRED
32 | *
A required parameter/field was absent
33 | *
LIMIT_REACHED
34 | *
Operation denied due to data model limit
35 | *
QUOTA_REACHED
36 | *
Operation denied due to user storage limit
37 | *
INVALID_AUTH
38 | *
Username and/or password incorrect
39 | *
AUTH_EXPIRED
40 | *
Authentication token expired
41 | *
DATA_CONFLICT
42 | *
Change denied due to data model conflict
43 | *
ENML_VALIDATION
44 | *
Content of submitted note was malformed
45 | *
SHARD_UNAVAILABLE
46 | *
Service shard with account data is temporarily down
47 | *
LEN_TOO_SHORT
48 | *
Operation denied due to data model limit, where something such
49 | * as a string length was too short
50 | *
LEN_TOO_LONG
51 | *
Operation denied due to data model limit, where something such
52 | * as a string length was too long
53 | *
TOO_FEW
54 | *
Operation denied due to data model limit, where there were
55 | * too few of something.
56 | *
TOO_MANY
57 | *
Operation denied due to data model limit, where there were
58 | * too many of something.
59 | *
UNSUPPORTED_OPERATION
60 | *
Operation denied because it is currently unsupported.
61 | *
TAKEN_DOWN
62 | *
Operation denied because access to the corresponding object is
63 | * prohibited in response to a take-down notice.
64 | *
RATE_LIMIT_REACHED
65 | *
Operation denied because the calling application has reached
66 | * its hourly API call limit for this user.
67 | *
BUSINESS_SECURITY_LOGIN_REQUIRED
68 | *
Access to a business account has been denied because the user must complete
69 | * additional steps in order to comply with business security requirements.
70 | *
DEVICE_LIMIT_REACHED
71 | *
Operation denied because the user has exceeded their maximum allowed
72 | * number of devices.
73 | *
74 | */
75 | struct QEVERCLOUD_EXPORT EDAMErrorCode
76 | {
77 | enum type
78 | {
79 | UNKNOWN = 1,
80 | BAD_DATA_FORMAT = 2,
81 | PERMISSION_DENIED = 3,
82 | INTERNAL_ERROR = 4,
83 | DATA_REQUIRED = 5,
84 | LIMIT_REACHED = 6,
85 | QUOTA_REACHED = 7,
86 | INVALID_AUTH = 8,
87 | AUTH_EXPIRED = 9,
88 | DATA_CONFLICT = 10,
89 | ENML_VALIDATION = 11,
90 | SHARD_UNAVAILABLE = 12,
91 | LEN_TOO_SHORT = 13,
92 | LEN_TOO_LONG = 14,
93 | TOO_FEW = 15,
94 | TOO_MANY = 16,
95 | UNSUPPORTED_OPERATION = 17,
96 | TAKEN_DOWN = 18,
97 | RATE_LIMIT_REACHED = 19,
98 | BUSINESS_SECURITY_LOGIN_REQUIRED = 20,
99 | DEVICE_LIMIT_REACHED = 21
100 | };
101 | };
102 |
103 |
104 | } // namespace qevercloud
105 |
106 | #endif // QEVERCLOUD_GENERATED_EDAMERRORCODE_H
107 |
--------------------------------------------------------------------------------
/src/qevercloud/globals.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | namespace qevercloud {
7 |
8 | QNetworkAccessManager * evernoteNetworkAccessManager()
9 | {
10 | static QSharedPointer pNetworkAccessManager;
11 | static QMutex networkAccessManagerMutex;
12 | QMutexLocker mutexLocker(&networkAccessManagerMutex);
13 | if (pNetworkAccessManager.isNull()) {
14 | pNetworkAccessManager = QSharedPointer(new QNetworkAccessManager);
15 | }
16 | return pNetworkAccessManager.data();
17 | }
18 |
19 | int libraryVersion()
20 | {
21 | return 4*10000 + 0*100 + 0;
22 | }
23 |
24 | } // namespace qevercloud
25 |
--------------------------------------------------------------------------------
/src/qevercloud/globals.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_GLOBALS_H
10 | #define QEVERCLOUD_GLOBALS_H
11 |
12 | #include "export.h"
13 | #include
14 |
15 | /**
16 | * All the library lives in this namespace.
17 | */
18 | namespace qevercloud {
19 |
20 | /**
21 | * All network request made by QEverCloud - including OAuth - are
22 | * served by this NetworkAccessManager.
23 | *
24 | * Use this function to handle proxy authentication requests etc.
25 | */
26 | QEVERCLOUD_EXPORT QNetworkAccessManager * evernoteNetworkAccessManager();
27 |
28 | /**
29 | * qevercloud library version.
30 | */
31 | QEVERCLOUD_EXPORT int libraryVersion();
32 |
33 | } // namespace qevercloud
34 |
35 | #endif // QEVERCLOUD_GLOBALS_H
36 |
--------------------------------------------------------------------------------
/src/qevercloud/http.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 | #include "http.h"
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | /** @cond HIDDEN_SYMBOLS */
19 |
20 | namespace qevercloud {
21 |
22 | ReplyFetcher::ReplyFetcher(QObject * parent) :
23 | QObject(parent),
24 | m_success(false),
25 | m_httpStatusCode(0)
26 | {
27 | m_ticker = new QTimer(this);
28 | QObject::connect(m_ticker, QEC_SIGNAL(QTimer,timeout), this, QEC_SLOT(ReplyFetcher,checkForTimeout));
29 | }
30 |
31 | void ReplyFetcher::start(QNetworkAccessManager * nam, QUrl url)
32 | {
33 | QNetworkRequest request;
34 | request.setUrl(url);
35 | start(nam, request);
36 | }
37 |
38 | void ReplyFetcher::start(QNetworkAccessManager * nam, QNetworkRequest request, QByteArray postData)
39 | {
40 | m_httpStatusCode= 0;
41 | m_errorText.clear();
42 | m_receivedData.clear();
43 | m_success = true; // not in finished() signal handler, it might not be called according to the docs
44 | // besides, I've added timeout feature
45 |
46 | m_lastNetworkTime = QDateTime::currentMSecsSinceEpoch();
47 | m_ticker->start(1000);
48 |
49 | if (postData.isNull()) {
50 | m_reply = QSharedPointer(nam->get(request), &QObject::deleteLater);
51 | }
52 | else {
53 | m_reply = QSharedPointer(nam->post(request, postData), &QObject::deleteLater);
54 | }
55 |
56 | QObject::connect(m_reply.data(), QEC_SIGNAL(QNetworkReply,finished), this, QEC_SLOT(ReplyFetcher,onFinished));
57 | QObject::connect(m_reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
58 | QObject::connect(m_reply.data(), QEC_SIGNAL(QNetworkReply,sslErrors,QList), this, QEC_SLOT(ReplyFetcher,onSslErrors,QList));
59 | QObject::connect(m_reply.data(), QEC_SIGNAL(QNetworkReply,downloadProgress,qint64,qint64), this, QEC_SLOT(ReplyFetcher,onDownloadProgress,qint64,qint64));
60 | }
61 |
62 | void ReplyFetcher::onDownloadProgress(qint64, qint64)
63 | {
64 | m_lastNetworkTime = QDateTime::currentMSecsSinceEpoch();
65 | }
66 |
67 | void ReplyFetcher::checkForTimeout()
68 | {
69 | const int connectionTimeout = 30*1000;
70 | if ((m_lastNetworkTime - QDateTime::currentMSecsSinceEpoch()) > connectionTimeout) {
71 | setError(QStringLiteral("Connection timeout."));
72 | }
73 | }
74 |
75 | void ReplyFetcher::onFinished()
76 | {
77 | m_ticker->stop();
78 |
79 | if (!m_success) {
80 | return;
81 | }
82 |
83 | m_receivedData = m_reply->readAll();
84 | m_httpStatusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
85 |
86 | QObject::disconnect(m_reply.data());
87 | emit replyFetched(this);
88 | }
89 |
90 | void ReplyFetcher::onError(QNetworkReply::NetworkError error)
91 | {
92 | Q_UNUSED(error)
93 | setError(m_reply->errorString());
94 | }
95 |
96 | void ReplyFetcher::onSslErrors(QList errors)
97 | {
98 | QString errorText = QStringLiteral("SSL Errors:\n");
99 |
100 | for(int i = 0, numErrors = errors.size(); i < numErrors; ++i) {
101 | const QSslError & error = errors[i];
102 | errorText += error.errorString().append(QStringLiteral("\n"));
103 | }
104 |
105 | setError(errorText);
106 | }
107 |
108 | void ReplyFetcher::setError(QString errorText)
109 | {
110 | m_success = false;
111 | m_ticker->stop();
112 | m_errorText = errorText;
113 | QObject::disconnect(m_reply.data());
114 | emit replyFetched(this);
115 | }
116 |
117 | QByteArray simpleDownload(QNetworkAccessManager* nam, QNetworkRequest request,
118 | QByteArray postData, int * httpStatusCode)
119 | {
120 | ReplyFetcher * fetcher = new ReplyFetcher;
121 | QEventLoop loop;
122 | QObject::connect(fetcher, SIGNAL(replyFetched(QObject*)), &loop, SLOT(quit()));
123 |
124 | ReplyFetcherLauncher * fetcherLauncher = new ReplyFetcherLauncher(fetcher, nam, request, postData);
125 | QTimer::singleShot(0, fetcherLauncher, SLOT(start()));
126 | loop.exec(QEventLoop::ExcludeUserInputEvents);
127 |
128 | fetcherLauncher->deleteLater();
129 |
130 | if (httpStatusCode) {
131 | *httpStatusCode = fetcher->httpStatusCode();
132 | }
133 |
134 | if (fetcher->isError()) {
135 | QString errorText = fetcher->errorText();
136 | fetcher->deleteLater();
137 | throw EverCloudException(errorText);
138 | }
139 |
140 | QByteArray receivedData = fetcher->receivedData();
141 | fetcher->deleteLater();
142 | return receivedData;
143 | }
144 |
145 | QNetworkRequest createEvernoteRequest(QString url)
146 | {
147 | QNetworkRequest request;
148 | request.setUrl(url);
149 | request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-thrift"));
150 |
151 | #if QT_VERSION < 0x050000
152 | request.setRawHeader("User-Agent", QString::fromUtf8("QEverCloud %1.%2").arg(libraryVersion() / 10000).arg(libraryVersion() % 10000).toLatin1());
153 | #else
154 | request.setHeader(QNetworkRequest::UserAgentHeader, QStringLiteral("QEverCloud %1.%2").arg(libraryVersion() / 10000).arg(libraryVersion() % 10000));
155 | #endif
156 |
157 | request.setRawHeader("Accept", "application/x-thrift");
158 | return request;
159 | }
160 |
161 | QByteArray askEvernote(QString url, QByteArray postData)
162 | {
163 | int httpStatusCode = 0;
164 | QByteArray reply = simpleDownload(evernoteNetworkAccessManager(), createEvernoteRequest(url), postData, &httpStatusCode);
165 |
166 | if (httpStatusCode != 200) {
167 | throw EverCloudException(QStringLiteral("HTTP Status Code = %1").arg(httpStatusCode));
168 | }
169 |
170 | return reply;
171 | }
172 |
173 | ReplyFetcherLauncher::ReplyFetcherLauncher(ReplyFetcher * fetcher, QNetworkAccessManager * nam,
174 | const QNetworkRequest & request, const QByteArray & postData) :
175 | QObject(nam),
176 | m_fetcher(fetcher),
177 | m_nam(nam),
178 | m_request(request),
179 | m_postData(postData)
180 | {}
181 |
182 | void ReplyFetcherLauncher::start()
183 | {
184 | m_fetcher->start(m_nam, m_request, m_postData);
185 | }
186 |
187 | } // namespace qevercloud
188 |
189 | /** @endcond */
190 |
--------------------------------------------------------------------------------
/src/qevercloud/http.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_HTTP_H
10 | #define QEVERCLOUD_HTTP_H
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | /** @cond HIDDEN_SYMBOLS */
25 |
26 | namespace qevercloud {
27 |
28 | QNetworkAccessManager * evernoteNetworkAccessManager();
29 |
30 | // the class greatly simplifies QNetworkReply handling
31 | class ReplyFetcher: public QObject
32 | {
33 | Q_OBJECT
34 | public:
35 | ReplyFetcher(QObject * parent = Q_NULLPTR);
36 |
37 | void start(QNetworkAccessManager * nam, QUrl url);
38 | // if !postData.isNull() then POST will be issued instead of GET
39 | void start(QNetworkAccessManager * nam, QNetworkRequest request, QByteArray postData = QByteArray());
40 | bool isError() { return !m_success; }
41 | QString errorText() { return m_errorText; }
42 | QByteArray receivedData() { return m_receivedData; }
43 | int httpStatusCode() { return m_httpStatusCode; }
44 |
45 | Q_SIGNALS:
46 | void replyFetched(QObject*); // sends itself
47 |
48 | private Q_SLOTS:
49 | void onFinished();
50 | void onError(QNetworkReply::NetworkError);
51 | void onSslErrors(QList l);
52 | void onDownloadProgress(qint64, qint64);
53 | void checkForTimeout();
54 |
55 | private:
56 | void setError(QString errorText);
57 |
58 | private:
59 | QSharedPointer m_reply;
60 | bool m_success;
61 | QString m_errorText;
62 | QByteArray m_receivedData;
63 | int m_httpStatusCode;
64 | QTimer* m_ticker;
65 | qint64 m_lastNetworkTime;
66 | };
67 |
68 | QNetworkRequest createEvernoteRequest(QString url);
69 |
70 | QByteArray askEvernote(QString url, QByteArray postData);
71 |
72 | QByteArray simpleDownload(QNetworkAccessManager * nam, QNetworkRequest request,
73 | QByteArray postData = QByteArray(), int * httpStatusCode = Q_NULLPTR);
74 |
75 | class ReplyFetcherLauncher: public QObject
76 | {
77 | Q_OBJECT
78 | public:
79 | explicit ReplyFetcherLauncher(ReplyFetcher * fetcher, QNetworkAccessManager * nam,
80 | const QNetworkRequest & request, const QByteArray & postData);
81 |
82 | public Q_SLOTS:
83 | void start();
84 |
85 | private:
86 | ReplyFetcher * m_fetcher;
87 | QNetworkAccessManager * m_nam;
88 | QNetworkRequest m_request;
89 | QByteArray m_postData;
90 | };
91 |
92 | } // namespace qevercloud
93 |
94 | /** @endcond */
95 |
96 | #endif // QEVERCLOUD_HTTP_H
97 |
--------------------------------------------------------------------------------
/src/qevercloud/impl.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_IMPL_H
10 | #define QEVERCLOUD_IMPL_H
11 |
12 | #include
13 | #include
14 | #include
15 | #include "http.h"
16 | #include "thrift.h"
17 |
18 | /**
19 |
20 | @mainpage About QEverCloud
21 |
22 | This library presents complete Evernote SDK for Qt.
23 | All the functionality that is described on Evernote site
24 | is implemented and ready to use. In particular OAuth autentication is implemented.
25 |
26 | Include *QEverCloud.h* or *QEverCloudOAuth.h* to use the library. The latter header is needed if you use OAuth functionality.
27 |
28 | QEverCloud on GitHub
29 |
30 | */
31 |
32 | namespace qevercloud {
33 |
34 | /** @cond HIDDEN_SYMBOLS */
35 |
36 | ThriftException readThriftException(ThriftBinaryBufferReader & reader);
37 |
38 | void throwEDAMSystemException(const EDAMSystemException & baseException);
39 |
40 | /** @endcond */
41 |
42 | } // namespace qevercloud
43 |
44 | #endif // QEVERCLOUD_IMPL_H
45 |
--------------------------------------------------------------------------------
/src/qevercloud/oauth.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_OAUTH_H
10 | #define QEVERCLOUD_OAUTH_H
11 |
12 | // Workarounding https://bugreports.qt.io/browse/QTBUG-28885
13 | #if defined(_MSC_VER) && (_MSC_VER <= 1600)
14 | #define QT_NO_UNICODE_LITERAL
15 | #endif
16 |
17 | #include "generated/types.h"
18 | #include "export.h"
19 | #include "qt4helpers.h"
20 | #include
21 | #include
22 |
23 | #if defined(_MSC_VER) && _MSC_VER <= 1600 // MSVC <= 2010
24 | // VS2010 is supposed to be C++11 but does not fulfull the entire standard.
25 | #ifdef QStringLiteral
26 | #undef QStringLiteral
27 | #define QStringLiteral(str) QString::fromUtf8("" str "", sizeof(str) - 1)
28 | #endif
29 | #endif
30 |
31 | namespace qevercloud {
32 |
33 | /**
34 | * @brief Sets the function to use for nonce generation for OAuth authentication.
35 | *
36 | * The default algorithm uses qrand() so do not forget to call qsrand() in your application!
37 | *
38 | * qrand() is not guaranteed to be cryptographically strong. I try to amend the fact by using
39 | * QUuid::createUuid() which uses /dev/urandom if it's available. But this is no guarantee either.
40 | * So if you want total control over nonce generation you can write you own algorithm.
41 | *
42 | * setNonceGenerator is NOT thread safe.
43 | */
44 | void setNonceGenerator(quint64 (*nonceGenerator)());
45 |
46 | /** @cond HIDDEN_SYMBOLS */
47 | class EvernoteOAuthWebViewPrivate;
48 | /** @endcond */
49 |
50 | /**
51 | * @brief The class is tailored specifically for OAuth authorization with Evernote.
52 | *
53 | * While it is functional by itself you probably will prefer to use EvernoteOAuthDialog.
54 | *
55 | * %Note that you have to include QEverCloudOAuth.h header.
56 | *
57 | * By deafult EvernoteOAuthWebView uses qrand() for generating nonce so do not forget to call qsrand()
58 | * in your application. See @link setNonceGenerator @endlink If you want more control over nonce generation.
59 | */
60 | class QEVERCLOUD_EXPORT EvernoteOAuthWebView: public QWidget
61 | {
62 | Q_OBJECT
63 | public:
64 | EvernoteOAuthWebView(QWidget * parent = Q_NULLPTR);
65 |
66 | /**
67 | * This function starts the OAuth sequence. In the end of the sequence will be emitted one of the signals: authenticationSuceeded or authenticationFailed.
68 | *
69 | * Do not call the function while its call is in effect, i.e. one of the signals is not emitted.
70 | *
71 | * @param host
72 | * Evernote host to authorize with. You need one of this:
73 | *
74 | *
"www.evernote.com" - the production service. It's the default value.
75 | *
"sandox.evernote.com" - the developers "sandbox" service
76 | *
77 | * @param consumerKey
78 | * get it from the Evernote
79 | * @param consumerSecret
80 | * along with this
81 | */
82 | void authenticate(QString host, QString consumerKey, QString consumerSecret);
83 |
84 | /** @return true if the last call to authenticate resulted in a successful authentication. */
85 | bool isSucceeded() const;
86 |
87 | /** @return error message resulted from the last call to authenticate */
88 | QString oauthError() const;
89 |
90 | /** Holds data that is returned by Evernote on a successful authentication */
91 | struct OAuthResult
92 | {
93 | QString noteStoreUrl; ///< note store url for the user; no need to question UserStore::getNoteStoreUrl for it.
94 | Timestamp expires; ///< authenticationToken time of expiration.
95 | QString shardId; ///< usually is not used
96 | UserID userId; ///< same as PublicUserInfo::userId
97 | QString webApiUrlPrefix; ///< see PublicUserInfo::webApiUrlPrefix
98 | QString authenticationToken; ///< This is what this all was for!
99 | };
100 |
101 | /** @returns the result of the last authentication, i.e. authenticate() call.*/
102 | OAuthResult oauthResult() const;
103 |
104 | /** The method is useful to specify default size for a EverOAuthWebView. */
105 | void setSizeHint(QSize sizeHint);
106 |
107 | virtual QSize sizeHint() const Q_DECL_OVERRIDE;
108 |
109 | Q_SIGNALS:
110 | /** Emitted when the OAuth sequence started with authenticate() call is finished */
111 | void authenticationFinished(bool success);
112 |
113 | /** Emitted when the OAuth sequence is successfully finished. Call oauthResult() to get the data.*/
114 | void authenticationSuceeded();
115 |
116 | /** Emitted when the OAuth sequence is finished with a failure. Some error info may be available with errorText().*/
117 | void authenticationFailed();
118 |
119 | private:
120 | EvernoteOAuthWebViewPrivate * const d_ptr;
121 | Q_DECLARE_PRIVATE(EvernoteOAuthWebView)
122 | };
123 |
124 | /** @cond HIDDEN_SYMBOLS */
125 | class EvernoteOAuthDialogPrivate;
126 | /** @endcond */
127 |
128 | /**
129 | * @brief Authorizes your app with the Evernote service by means of OAuth authentication.
130 | *
131 | * Intended usage:
132 | *
133 | @code
134 | #include
135 |
136 | OAuthDialog d(myConsumerKey, myConsumerSecret);
137 | if(d.exec() == QDialog::Accepted) {
138 | OAuthDialog::OAuthResult res = d.oauthResult();
139 | // Connect to Evernote
140 | ...
141 | } else {
142 | QString errorText = d.oauthError();
143 | // handle an authentication error
144 | ...
145 | }
146 |
147 | @endcode
148 | *
149 | * %Note that you have to include QEverCloudOAuth.h header.
150 | *
151 | * By default EvernoteOAuthDialog uses qrand() for generating nonce so do not forget to call qsrand()
152 | * in your application. See @link setNonceGenerator @endlink If you want more control over nonce generation.
153 | */
154 |
155 | class QEVERCLOUD_EXPORT EvernoteOAuthDialog: public QDialog
156 | {
157 | Q_OBJECT
158 | public:
159 | typedef EvernoteOAuthWebView::OAuthResult OAuthResult;
160 |
161 | /** Constructs the dialog.
162 | *
163 | * @param host
164 | * Evernote host to authorize with. You need one of this:
165 | *
166 | *
"www.evernote.com" - the production service. It's the default value.
167 | *
"sandox.evernote.com" - the developers "sandbox" service
168 | *
169 | * @param consumerKey
170 | * get it from the Evernote
171 | * @param consumerSecret
172 | * along with this
173 | */
174 | EvernoteOAuthDialog(QString consumerKey, QString consumerSecret, QString host = QStringLiteral("www.evernote.com"), QWidget * parent = Q_NULLPTR);
175 | ~EvernoteOAuthDialog();
176 |
177 | /**
178 | * The dialog adjusts its initial size automatically based on the contained QWebView preffered size.
179 | * Use this method to set the size.
180 | *
181 | * @param sizeHint will be used as the preffered size of the contained QWebView.
182 | */
183 | void setWebViewSizeHint(QSize sizeHint);
184 |
185 | /** @return true in case of a successful authentication.
186 | * You probably better chech exec() return value instead.
187 | */
188 | bool isSucceeded() const;
189 |
190 | /**
191 | * @return In case of an authentification error may return some information about the error.
192 | */
193 | QString oauthError() const;
194 |
195 | /**
196 | * @return the result of a successful authentication.
197 | */
198 | OAuthResult oauthResult() const;
199 |
200 | /**
201 | * @return
202 | * QDialog::Accepted on a successful authentication.
203 | */
204 | #if QT_VERSION < 0x050000
205 | int exec();
206 | #else
207 | virtual int exec() Q_DECL_OVERRIDE;
208 | #endif
209 |
210 | /** Shows the dialog as a window modal dialog, returning immediately.
211 | */
212 | #if QT_VERSION < 0x050000
213 | void open();
214 | #else
215 | virtual void open() Q_DECL_OVERRIDE;
216 | #endif
217 |
218 | private:
219 | EvernoteOAuthDialogPrivate * const d_ptr;
220 | Q_DECLARE_PRIVATE(EvernoteOAuthDialog)
221 | };
222 |
223 | } // namespace qevercloud
224 |
225 | #endif // QEVERCLOUD_OAUTH_H
226 |
--------------------------------------------------------------------------------
/src/qevercloud/qt4helpers.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | *
8 | * This header provides the "backports" of several Qt5 macros into Qt4
9 | * so that one can use Qt5 candies with Qt4 as well
10 | */
11 |
12 | #ifndef QEVERCLOUD_QT4_HELPERS_H
13 | #define QEVERCLOUD_QT4_HELPERS_H
14 |
15 | #include
16 | #include
17 |
18 | #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
19 |
20 | #if __cplusplus >= 201103L
21 |
22 | #ifndef Q_DECL_OVERRIDE
23 | #define Q_DECL_OVERRIDE override
24 | #endif
25 |
26 | #ifndef Q_DECL_FINAL
27 | #define Q_DECL_FINAL final
28 | #endif
29 |
30 | #ifndef Q_STATIC_ASSERT_X
31 | #define Q_STATIC_ASSERT_X(x1,x2) static_assert(x1, x2)
32 | #endif
33 |
34 | #ifndef Q_DECL_EQ_DELETE
35 | #define Q_DECL_EQ_DELETE = delete
36 | #endif
37 |
38 | #ifndef Q_NULLPTR
39 | #define Q_NULLPTR nullptr
40 | #endif
41 |
42 | #else // __cplusplus
43 |
44 | #ifndef Q_DECL_OVERRIDE
45 | #define Q_DECL_OVERRIDE
46 | #endif
47 |
48 | #ifndef Q_DECL_FINAL
49 | #define Q_DECL_FINAL
50 | #endif
51 |
52 | #ifndef Q_STATIC_ASSERT_X
53 | #define Q_STATIC_ASSERT_X(x1,x2)
54 | #endif
55 |
56 | #ifndef Q_DECL_EQ_DELETE
57 | #define Q_DECL_EQ_DELETE
58 | #endif
59 |
60 | #ifndef Q_NULLPTR
61 | #define Q_NULLPTR NULL
62 | #endif
63 |
64 | #endif // __cplusplus
65 |
66 | #ifndef QStringLiteral
67 | #define QStringLiteral(x) QString::fromUtf8(x, sizeof(x) - 1)
68 | #endif
69 |
70 | #define QEC_SIGNAL(className, methodName, ...) SIGNAL(methodName(__VA_ARGS__))
71 | #define QEC_SLOT(className, methodName, ...) SLOT(methodName(__VA_ARGS__))
72 |
73 | #else // QT_VERSION
74 |
75 | // VS2010 is supposed to be C++11 but does not fulfull the entire standard.
76 | #if defined(_MSC_VER) && _MSC_VER <= 1600 // MSVC <= 2010
77 |
78 | #ifdef Q_DECL_OVERRIDE
79 | #undef Q_DECL_OVERRIDE
80 | #endif
81 | #define Q_DECL_OVERRIDE
82 |
83 | #endif // VS2010
84 |
85 | #define QEC_SIGNAL(className, methodName, ...) &className::methodName
86 | #define QEC_SLOT(className, methodName, ...) &className::methodName
87 |
88 | #endif // QT_VERSION
89 |
90 | #endif // QEVERCLOUD_QT4_HELPERS_H
91 |
--------------------------------------------------------------------------------
/src/qevercloud/services_nongenerated.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | namespace qevercloud {
14 |
15 | /**
16 | * @brief Constructs UserStore object.
17 | * @param host
18 | * www.evernote.com or sandbox.evernote.com
19 | * @param authenticationToken
20 | * This token that will be used as the default token.
21 | */
22 | UserStore::UserStore(QString host, QString authenticationToken, QObject * parent) :
23 | QObject(parent)
24 | {
25 | QUrl url;
26 | url.setScheme(QStringLiteral("https"));
27 | url.setHost(host);
28 | url.setPath(QStringLiteral("/edam/user"));
29 | m_url = url.toString(QUrl::StripTrailingSlash);
30 | setAuthenticationToken(authenticationToken);
31 | }
32 |
33 | /**
34 | * Constructs NoteStore object.
35 | * @param noteStoreUrl
36 | * EDAM NoteStore service url. In general it's different for different users.
37 | * @param authenticationToken
38 | * This token that will be used as the default token.
39 | *
40 | */
41 | NoteStore::NoteStore(QString noteStoreUrl, QString authenticationToken, QObject * parent) :
42 | QObject(parent)
43 | {
44 | setNoteStoreUrl(noteStoreUrl);
45 | setAuthenticationToken(authenticationToken);
46 | }
47 |
48 | /**
49 | * Constructs NoteStore object.
50 | *
51 | * noteStoreUrl and possibly authenticationToken are expected to be specified later.
52 | */
53 | NoteStore::NoteStore(QObject * parent) :
54 | QObject(parent)
55 | {}
56 |
57 | /** @fn qevercloud::UserStore::setAuthenticationToken
58 | * Sets a value that will be used as the default token.
59 | * */
60 |
61 | /** @fn qevercloud::UserStore::authenticationToken
62 | * @returns the default authentication token value.
63 | * */
64 |
65 | /** @fn qevercloud::NoteStore::setAuthenticationToken
66 | * Sets a value that will be used as the default token.
67 | * */
68 |
69 | /** @fn qevercloud::NoteStore::authenticationToken
70 | * @returns the default authentication token value.
71 | * */
72 |
73 | /** @fn qevercloud::NoteStore::setNoteStoreUrl
74 | * Sets a value that will be used as EDAM NoteStore service url by this object.
75 | * */
76 |
77 | /** @fn qevercloud::NoteStore::authenticationToken
78 | * @returns EDAM NoteStore service url that is used by this NoteStore object.
79 | * */
80 |
81 | } // namespace qevercloud
82 |
--------------------------------------------------------------------------------
/src/qevercloud/thumbnail.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #include
10 | #include "http.h"
11 |
12 | namespace qevercloud {
13 |
14 | class ThumbnailPrivate
15 | {
16 | public:
17 | QString m_host;
18 | QString m_shardId;
19 | QString m_authenticationToken;
20 | int m_size;
21 | Thumbnail::ImageType::type m_imageType;
22 | };
23 |
24 | Thumbnail::Thumbnail():
25 | d_ptr(new ThumbnailPrivate)
26 | {
27 | d_ptr->m_size = 300;
28 | d_ptr->m_imageType = ImageType::PNG;
29 | }
30 |
31 |
32 | Thumbnail::Thumbnail(QString host, QString shardId, QString authenticationToken,
33 | int size, Thumbnail::ImageType::type imageType) :
34 | d_ptr(new ThumbnailPrivate)
35 | {
36 | d_ptr->m_host = host;
37 | d_ptr->m_shardId = shardId;
38 | d_ptr->m_authenticationToken = authenticationToken;
39 | d_ptr->m_size = size;
40 | d_ptr->m_imageType = imageType;
41 | }
42 |
43 | Thumbnail::~Thumbnail()
44 | {
45 | delete d_ptr;
46 | }
47 |
48 | Thumbnail & Thumbnail::setHost(QString host)
49 | {
50 | d_ptr->m_host = host;
51 | return *this;
52 | }
53 |
54 | Thumbnail & Thumbnail::setShardId(QString shardId)
55 | {
56 | d_ptr->m_shardId = shardId;
57 | return *this;
58 | }
59 |
60 | Thumbnail & Thumbnail::setAuthenticationToken(QString authenticationToken)
61 | {
62 | d_ptr->m_authenticationToken = authenticationToken;
63 | return *this;
64 | }
65 |
66 | Thumbnail & Thumbnail::setSize(int size)
67 | {
68 | d_ptr->m_size = size;
69 | return *this;
70 | }
71 |
72 | Thumbnail & Thumbnail::setImageType(ImageType::type imageType)
73 | {
74 | d_ptr->m_imageType = imageType;
75 | return *this;
76 | }
77 |
78 | QByteArray Thumbnail::download(Guid guid, bool isPublic, bool isResourceGuid)
79 | {
80 | int httpStatusCode = 0;
81 | QPair request = createPostRequest(guid, isPublic, isResourceGuid);
82 |
83 | QByteArray reply = simpleDownload(evernoteNetworkAccessManager(), request.first,
84 | request.second, &httpStatusCode);
85 | if (httpStatusCode != 200) {
86 | throw EverCloudException(QStringLiteral("HTTP Status Code = %1").arg(httpStatusCode));
87 | }
88 |
89 | return reply;
90 | }
91 |
92 | AsyncResult* Thumbnail::downloadAsync(Guid guid, bool isPublic, bool isResourceGuid)
93 | {
94 | QPair pair = createPostRequest(guid, isPublic, isResourceGuid);
95 | return new AsyncResult(pair.first, pair.second);
96 | }
97 |
98 | QPair Thumbnail::createPostRequest(Guid guid, bool isPublic, bool isResourceGuid)
99 | {
100 | Q_D(Thumbnail);
101 |
102 | QByteArray postData = ""; // not QByteArray()! or else ReplyFetcher will not work.
103 | QNetworkRequest request;
104 |
105 | QString urlPattern;
106 | if(isResourceGuid) {
107 | urlPattern = QStringLiteral("https://%1/shard/%2/thm/res/%3");
108 | }
109 | else {
110 | urlPattern = QStringLiteral("https://%1/shard/%2/thm/note/%3");
111 | }
112 |
113 | QString url = urlPattern.arg(d->m_host, d->m_shardId, guid);
114 |
115 | QString ext;
116 | switch(d->m_imageType)
117 | {
118 | case ImageType::BMP:
119 | ext = QStringLiteral(".bmp");
120 | break;
121 | case ImageType::GIF:
122 | ext = QStringLiteral(".gif");
123 | break;
124 | case ImageType::JPEG:
125 | ext = QStringLiteral(".jpg");
126 | break;
127 | default:
128 | ext = QStringLiteral(".png");
129 | break;
130 | }
131 | url += ext;
132 |
133 | if (d->m_size != 300) {
134 | url += QStringLiteral("?size=%1").arg(d->m_size);
135 | }
136 |
137 | request.setUrl(QUrl(url));
138 | request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
139 |
140 | if (!isPublic) {
141 | postData = QByteArray("auth=")+ QUrl::toPercentEncoding(d->m_authenticationToken);
142 | }
143 |
144 | return qMakePair(request, postData);
145 | }
146 |
147 | } // namespace qevercloud
148 |
--------------------------------------------------------------------------------
/src/qevercloud/thumbnail.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Original work: Copyright (c) 2014 Sergey Skoblikov
3 | * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
4 | *
5 | * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
6 | * https://opensource.org/licenses/MIT
7 | */
8 |
9 | #ifndef QEVERCLOUD_THUMBNAIL_H
10 | #define QEVERCLOUD_THUMBNAIL_H
11 |
12 | #include "export.h"
13 | #include "AsyncResult.h"
14 | #include "generated/types.h"
15 | #include
16 | #include
17 | #include
18 |
19 | namespace qevercloud {
20 |
21 | /** @cond HIDDEN_SYMBOLS */
22 | class ThumbnailPrivate;
23 | /** @endcond */
24 |
25 | /**
26 | * @brief The class is for downloading thumbnails for notes and resources from Evernote servers.
27 | *
28 | * These thumbnails are not available with general EDAM Thrift interface as explained in the
29 | * documentation.
30 | *
31 | * Usage:
32 | @code
33 |
34 | Thumbnail thumb("www.evernote.com", sharId, authenticationToken);
35 | QByteArray pngImage = thumb.download(noteGuid);
36 |
37 | @endcode
38 | *
39 | * By defualt 300x300 PNG images are requested.
40 | */
41 | class QEVERCLOUD_EXPORT Thumbnail
42 | {
43 | public:
44 | /**
45 | * Specifies image type of the returned thumbnail.
46 | *
47 | * Can be PNG, JPEG, GIF or BMP.
48 | */
49 | struct ImageType {
50 | enum type {PNG, JPEG, GIF, BMP};
51 | };
52 |
53 | /**
54 | * @brief Default constructor.
55 | *
56 | * host, shardId, authenticationToken have to be specified before calling
57 | * @link download @endlink or @link createPostRequest @endlink
58 | */
59 | Thumbnail();
60 |
61 | /**
62 | * @brief Constructs Thumbnail.
63 | * @param host
64 | * www.evernote.com or sandbox.evernote.com
65 | * @param shardId
66 | * You can get the value from UserStore service or as a result of an authentication.
67 | * @param authenticationToken
68 | * For working private notes/resources you must supply a valid authentication token.
69 | * For public resources the value specified is not used.
70 | * @param size
71 | * The size of the thumbnail. Evernote supports values from from 1 to 300. By defualt 300 is used.
72 | * @param imageType
73 | * Thumbnail image type. See ImageType. By default PNG is used.
74 | */
75 | Thumbnail(QString host, QString shardId, QString authenticationToken,
76 | int size = 300, ImageType::type imageType = ImageType::PNG);
77 |
78 | virtual ~Thumbnail();
79 |
80 | /**
81 | * @param host
82 | * www.evernote.com or sandbox.evernote.com
83 | */
84 | Thumbnail & setHost(QString host);
85 |
86 | /**
87 | * @param shardId
88 | * You can get the value from UserStore service or as a result of an authentication.
89 | */
90 | Thumbnail & setShardId(QString shardId);
91 |
92 | /**
93 | * @param authenticationToken
94 | * For working private notes/resources you must supply a valid authentication token.
95 | * For public resources the value specified is not used.
96 | */
97 | Thumbnail & setAuthenticationToken(QString authenticationToken);
98 |
99 | /**
100 | * @param size
101 | * The size of the thumbnail. Evernote supports values from from 1 to 300. By defualt 300 is used.
102 | */
103 | Thumbnail & setSize(int size);
104 |
105 | /**
106 | * @param imageType
107 | * Thumbnail image type. See ImageType. By default PNG is used.
108 | */
109 | Thumbnail & setImageType(ImageType::type imageType);
110 |
111 | /**
112 | * @brief Downloads the thumbnail for a resource or a note.
113 | * @param guid
114 | * The note or resource guid
115 | * @param isPublic
116 | * Specify true for public notes/resources. In this case authentication token is not sent to
117 | * with the request as it shoud be according to the docs.
118 | * @param isResourceGuid
119 | * true if guid denotes a resource and false if it denotes a note.
120 | * @return downloaded data.
121 | *
122 | */
123 | QByteArray download(Guid guid, bool isPublic = false, bool isResourceGuid = false);
124 |
125 | /** Asynchronous version of @link download @endlink function*/
126 | AsyncResult * downloadAsync(Guid guid, bool isPublic = false, bool isResourceGuid = false);
127 |
128 | /**
129 | * @brief Prepares a POST request for a thumbnail download.
130 | * @param guid
131 | * The note or resource guid
132 | * @param isPublic
133 | * Specify true for public notes/resources. In this case authentication token is not sent to
134 | * with the request as it shoud be according to the docs.
135 | * @param isResourceGuid
136 | * true if guid denotes a resource and false if it denotes a note.
137 | * @return a pair of QNetworkRequest for the POST request and data that must be posted with the request.
138 | */
139 | QPair createPostRequest(qevercloud::Guid guid,
140 | bool isPublic = false,
141 | bool isResourceGuid = false);
142 |
143 | private:
144 | ThumbnailPrivate * const d_ptr;
145 | Q_DECLARE_PRIVATE(Thumbnail)
146 | };
147 |
148 | } // namespace qevercloud
149 |
150 | #endif // QEVERCLOUD_THUMBNAIL_H
151 |
--------------------------------------------------------------------------------
/src/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | icon/appicon.ico
4 | icon/trayicon_black.ico
5 | icon/trayicon_white.ico
6 | icon/sizegripicon.svg
7 | style/about_stylesheet.qss
8 | style/note_stylesheet.qss
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/settings.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include "settings.h"
19 |
20 | #include
21 | #include
22 | #include
23 |
24 |
25 | static QMap defaultUserSettings =
26 | {
27 | {"sync_interval", 300},
28 | {"check_for_updates", true},
29 | {"dark_status_icon", false}
30 | };
31 |
32 | QString Settings::getSessionSettingsFileLocation()
33 | {
34 | return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).append("/session_settings.ini");
35 | }
36 |
37 | QString Settings::getUserSettingsFileLocation()
38 | {
39 | return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).append("/user_settings.ini");
40 | }
41 |
42 | void Settings::deleteAllSessionSettings()
43 | {
44 | QFile(getSessionSettingsFileLocation()).remove();
45 | }
46 |
47 | void Settings::deleteCurrentSessionSettings()
48 | {
49 | // Delete all session settings except for the session username.
50 | // This allows us to avoid deleting all unsynced notes if the same user is logging in again (i.e. after having to login again
51 | // after Evernote downtime, or auth key expiring).
52 | QString currentUsername = getSessionSetting("username");
53 | deleteAllSessionSettings();
54 | setSessionSetting("username", currentUsername);
55 | }
56 |
57 | QString Settings::getSessionSetting(QString settingKey)
58 | {
59 | QSettings settings(getSessionSettingsFileLocation(), QSettings::NativeFormat);
60 | return settings.value(settingKey).toString();
61 | }
62 |
63 | void Settings::setSessionSetting(QString settingKey, QString settingValue)
64 | {
65 | QSettings settings(getSessionSettingsFileLocation(), QSettings::NativeFormat);
66 | settings.setValue(settingKey, settingValue);
67 | }
68 |
69 | QVariant Settings::getUserSetting(QString settingKey)
70 | {
71 | QSettings settings(getUserSettingsFileLocation(), QSettings::NativeFormat);
72 |
73 | if(settings.contains(settingKey)) {
74 | return settings.value(settingKey);
75 | } else {
76 | // If settings value doesn't exist, return default value.
77 | return defaultUserSettings.value(settingKey);
78 | }
79 | }
80 |
81 | void Settings::setUserSetting(QString settingKey, QVariant settingValue)
82 | {
83 | QSettings settings(getUserSettingsFileLocation(), QSettings::NativeFormat);
84 | settings.setValue(settingKey, settingValue);
85 | }
86 |
--------------------------------------------------------------------------------
/src/settings.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef SETTINGS_H
19 | #define SETTINGS_H
20 |
21 | #include
22 | #include
23 | #include
24 |
25 |
26 | class Settings
27 | {
28 | public:
29 | static void deleteAllSessionSettings();
30 | static void deleteCurrentSessionSettings();
31 | static QString getSessionSetting(QString settingKey);
32 | static void setSessionSetting(QString settingKey, QString settingValue);
33 |
34 | static QVariant getUserSetting(QString settingKey);
35 | static void setUserSetting(QString settingKey, QVariant settingValue);
36 |
37 | private:
38 | static QString getSessionSettingsFileLocation();
39 | static QString getUserSettingsFileLocation();
40 | };
41 |
42 | #endif // SETTINGS_H
43 |
--------------------------------------------------------------------------------
/src/style/about_stylesheet.qss:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the eversticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 |
19 | /*
20 | * Widget styles
21 | */
22 |
23 | #AboutWindow QLabel
24 | {
25 | qproperty-alignment: AlignCenter;
26 | qproperty-wordWrap: true;
27 | }
28 |
--------------------------------------------------------------------------------
/src/style/note_stylesheet.qss:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the eversticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 |
19 | /*
20 | * Main widgets
21 | */
22 |
23 | #NoteTitleBar
24 | {
25 | /* Note titlebar darker colour */
26 | background-color: #fedd51;
27 | }
28 |
29 | #NoteContainer
30 | {
31 | border: 1px solid grey;
32 | }
33 |
34 | #NoteContainer,
35 | QScrollBar
36 | {
37 | /* Main note background colour */
38 | background-color: #ffec8e;
39 | }
40 |
41 | #NoteContainer QSizeGrip
42 | {
43 | image: url(:/icon/sizegripicon.svg);
44 | height: 24px;
45 | width: 24px;
46 | }
47 |
48 |
49 | /*
50 | * Widget styles
51 | */
52 |
53 | #NoteHeader #NoteHeaderTextEdit,
54 | #NoteScrollArea,
55 | #NoteScrollAreaContainer,
56 | #NoteTitleBar QToolButton
57 | {
58 | /* Some widgets should have transparent background */
59 | background: transparent;
60 | }
61 |
62 | #NoteTitleBar QToolButton
63 | {
64 | border: transparent;
65 | padding: 5px;
66 | color:#000000;
67 | }
68 |
69 | #NoteTitleBar QToolButton:hover
70 | {
71 | border: 1px solid grey;
72 | border-radius: 4px;
73 | }
74 |
75 | #NoteHeader #NoteHeaderTextEdit
76 | {
77 | border: 0px;
78 | color: #000000;
79 | font-size: 11pt;
80 | font-weight: bold;
81 | }
82 |
83 | #NoteHeader #NoteHeaderLine
84 | {
85 | margin-right: 100px;
86 | }
87 |
88 | #NoteScrollArea
89 | {
90 | border-style: none;
91 | }
92 |
93 |
94 | /*
95 | * Global scrollbar style
96 | */
97 |
98 | QScrollBar:vertical
99 | {
100 | width:18px;
101 | padding: 5px 5px 5px 5px;
102 | }
103 |
104 | QScrollBar::handle:vertical
105 | {
106 | background: grey;
107 | border-radius: 4px;
108 | }
109 |
110 | QScrollBar::add-line:vertical
111 | {
112 | height: 0px;
113 | }
114 |
115 | QScrollBar::sub-line:vertical
116 | {
117 | height: 0px;
118 | }
119 |
--------------------------------------------------------------------------------
/src/ui/about_widget.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the EverSticky project (https://eversticky.joeeey.com).
3 | * Copyright (c) 2021 Joey Miller.
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3.
8 | *
9 | * This program is distributed in the hope that it will be useful, but
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | * General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include "about_widget.h"
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 |
26 | AboutWidget::AboutWidget() : QDialog()
27 | {
28 | setObjectName("AboutWindow");
29 | setWindowTitle("EverSticky | About");
30 |
31 | QIcon icon(":/icon/appicon.ico");
32 | this->setWindowIcon(icon);
33 |
34 | // Read and apply note stylesheet
35 | QFile File(":style/about_stylesheet.qss");
36 | File.open(QFile::ReadOnly);
37 | QString styleSheet = QLatin1String(File.readAll());
38 | setStyleSheet(styleSheet);
39 |
40 |
41 | // Parent layout
42 | QVBoxLayout *parentLayout = new QVBoxLayout(this);
43 | parentLayout->setAlignment(Qt::AlignCenter);
44 | parentLayout->setContentsMargins(50,50,50,50);
45 | parentLayout->setSpacing(25);
46 |
47 | QPixmap appLogoPixmap = icon.pixmap(128);
48 |
49 | QLabel *appLogo = new QLabel(this);
50 | appLogo->setPixmap(appLogoPixmap);
51 | QLabel *appTitle = new QLabel("
EverSticky
", this);
52 | QLabel *appVersion = new QLabel("
Version " + QString::fromStdString(APP_VERSION) + "