aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt14
-rw-r--r--src/MainWindow.cpp387
-rw-r--r--src/Mime.cpp233
-rw-r--r--src/gpg/GpgContext.cpp164
-rw-r--r--src/main.cpp3
-rw-r--r--src/smtp/CMakeLists.txt6
-rw-r--r--src/smtp/emailaddress.cpp44
-rw-r--r--src/smtp/mimeattachment.cpp43
-rw-r--r--src/smtp/mimecontentformatter.cpp59
-rw-r--r--src/smtp/mimefile.cpp61
-rw-r--r--src/smtp/mimehtml.cpp46
-rw-r--r--src/smtp/mimeinlinefile.cpp42
-rw-r--r--src/smtp/mimemessage.cpp308
-rw-r--r--src/smtp/mimemultipart.cpp70
-rw-r--r--src/smtp/mimepart.cpp159
-rw-r--r--src/smtp/mimetext.cpp52
-rw-r--r--src/smtp/quotedprintable.cpp62
-rw-r--r--src/smtp/smtpclient.cpp407
-rw-r--r--src/ui/AboutDialog.cpp94
-rw-r--r--src/ui/AttachmentTableModel.cpp134
-rw-r--r--src/ui/CMakeLists.txt1
-rwxr-xr-xsrc/ui/FileEncryptionDialog.cpp37
-rwxr-xr-xsrc/ui/KeyMgmt.cpp2
-rw-r--r--src/ui/KeyServerImportDialog.cpp10
-rw-r--r--src/ui/KeyUploadDialog.cpp4
-rw-r--r--src/ui/SendMailDialog.cpp173
-rwxr-xr-xsrc/ui/SettingsDialog.cpp1143
-rw-r--r--src/ui/WaitingDialog.cpp9
-rw-r--r--src/ui/Wizard.cpp44
-rw-r--r--src/ui/help/AboutDialog.cpp215
-rw-r--r--src/ui/help/VersionCheckThread.cpp55
-rw-r--r--src/ui/keygen/KeygenDialog.cpp5
-rw-r--r--src/ui/keygen/SubkeyGenerateThread.cpp2
-rw-r--r--src/ui/keypair_details/KeyPairDetailTab.cpp85
-rw-r--r--src/ui/keypair_details/KeyPairSubkeyTab.cpp4
-rw-r--r--src/ui/keypair_details/KeyPairUIDTab.cpp7
-rw-r--r--src/ui/main_window/MainWindowSlotFunction.cpp324
-rw-r--r--src/ui/main_window/MainWindowSlotUI.cpp13
-rw-r--r--src/ui/main_window/MainWindowUI.cpp41
-rw-r--r--src/ui/widgets/Attachments.cpp180
-rw-r--r--src/ui/widgets/EditorPage.cpp3
-rw-r--r--src/ui/widgets/FilePage.cpp57
-rw-r--r--src/ui/widgets/InfoBoardWidget.cpp16
-rw-r--r--src/ui/widgets/KeyList.cpp5
-rw-r--r--src/ui/widgets/TextEdit.cpp11
45 files changed, 3147 insertions, 1687 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0d1336ba..ad56423d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -2,6 +2,7 @@ set(ALL_SOURCE_FILE)
add_subdirectory(gpg)
add_subdirectory(ui)
+add_subdirectory(smtp)
aux_source_directory(. BASE_SOURCE)
@@ -23,6 +24,8 @@ if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
elseif(LINUX)
file(COPY ${CMAKE_SOURCE_DIR}/resource/gpgfrontend DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN)
set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/gpgfrontend/usr/share)
+ else()
+ set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endif()
else()
set(RESOURCE_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
@@ -33,7 +36,9 @@ message(STATUS "RESOURCE_OUTPUT_DIRECTORY ${RESOURCE_OUTPUT_DIRECTORY}")
file(GLOB_RECURSE ALL_SOURCE_FILES RELACTIVE ${CMAKE_SOURCE_DIR}/src/*.cpp)
# Set Translation Files
-set(QT_TS_FILES gpgfrontend_en_us.ts gpgfrontend_zh_chs.ts gpgfrontend_zh_cht.ts gpg_frontend_fr.ts gpg_frontend_ru.ts)
+set(QT_TS_FILES
+ gpgfrontend_en_us.ts gpgfrontend_zh_cn.ts
+ gpgfrontend_fr.ts gpgfrontend_ru.ts gpgfrontend_es.ts)
list(TRANSFORM QT_TS_FILES PREPEND ${CMAKE_SOURCE_DIR}/resource/ts/)
message(STATUS "QT_TS_FILES ${QT_TS_FILES}")
set(QT_QM_FILES_OUTPUT_DIR ${RESOURCE_OUTPUT_DIRECTORY}/ts)
@@ -44,6 +49,7 @@ add_custom_target(translations DEPENDS ${QON_QM_FILES})
# Set Build Information
configure_file(${CMAKE_SOURCE_DIR}/include/GpgFrontend.h.in ${CMAKE_SOURCE_DIR}/include/GpgFrontend.h @ONLY)
+configure_file(${CMAKE_SOURCE_DIR}/include/GpgFrontendBuildInfo.h.in ${CMAKE_SOURCE_DIR}/include/GpgFrontendBuildInfo.h @ONLY)
# Copy Resource Files
file(COPY ${CMAKE_SOURCE_DIR}/resource/css DESTINATION ${RESOURCE_OUTPUT_DIRECTORY}/ FOLLOW_SYMLINK_CHAIN)
@@ -118,19 +124,19 @@ endif()
IF (MINGW)
message(STATUS "Link Application Static Library For MINGW")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl)
elseif(APPLE)
message(STATUS "Link Application Static Library For macOS")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl)
else()
message(STATUS "Link Application Static Library For UNIX")
target_link_libraries(${AppName}
- gpgfrontend-ui gpg
+ smtp gpgfrontend-ui gpg
Qt5::Network Qt5::PrintSupport Qt5::Widgets Qt5::Test Qt5::Core
crypto ssl pthread)
endif()
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index a59bd01d..eb8b96b1 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -23,208 +23,223 @@
*/
#include "MainWindow.h"
+#include "ui/help/VersionCheckThread.h"
MainWindow::MainWindow()
- : appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
-
- auto waitingDialog = new WaitingDialog(this);
-
- auto ctx_thread = QThread::create([&]() { mCtx = new GpgME::GpgContext(); });
-
- ctx_thread->start();
-
- while (ctx_thread->isRunning())
- QApplication::processEvents();
-
- waitingDialog->close();
-
-
- if (!mCtx->isGood()) {
- QMessageBox::critical(
- nullptr, tr("ENV Loading Failed"),
- tr("Gnupg is not installed correctly, please follow the ReadME "
- "instructions to install gnupg and then open GPGFrontend."));
- QCoreApplication::quit();
- exit(0);
- }
-
- /* get path were app was started */
- setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
- setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
-
- qDebug() << "Main Window" << this;
-
- edit = new TextEdit(this);
- setCentralWidget(edit);
-
- /* the list of Keys available*/
- mKeyList = new KeyList(mCtx, KeyListRow::SECRET_OR_PUBLIC_KEY,
- KeyListColumn::TYPE | KeyListColumn::NAME |
- KeyListColumn::EmailAddress |
- KeyListColumn::Usage | KeyListColumn::Validity,
- this);
- mKeyList->setFilter([](const GpgKey &key) -> bool {
- if (key.revoked || key.disabled || key.expired)
- return false;
- else
- return true;
- });
- mKeyList->slotRefresh();
-
- infoBoard = new InfoBoardWidget(this, mCtx, mKeyList);
-
- /* List of binary Attachments */
- attachmentDockCreated = false;
-
- /* Variable containing if restart is needed */
- this->slotSetRestartNeeded(false);
-
- keyMgmt = new KeyMgmt(mCtx, this);
- keyMgmt->hide();
- /* test attachmentdir for files alll 15s */
- auto *timer = new QTimer(this);
- connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder()));
- timer->start(5000);
-
- createActions();
- createMenus();
- createToolBars();
- createStatusBar();
- createDockWindows();
-
- connect(edit->tabWidget, SIGNAL(currentChanged(int)), this,
- SLOT(slotDisableTabActions(int)));
-
- mKeyList->addMenuAction(appendSelectedKeysAct);
- mKeyList->addMenuAction(copyMailAddressToClipboardAct);
- mKeyList->addMenuAction(showKeyDetailsAct);
- mKeyList->addMenuAction(refreshKeysFromKeyserverAct);
- mKeyList->addMenuAction(uploadKeyToServerAct);
-
- restoreSettings();
-
- // open filename if provided as first command line parameter
- QStringList args = qApp->arguments();
- if (args.size() > 1) {
- if (!args[1].startsWith("-")) {
- if (QFile::exists(args[1]))
- edit->loadFile(args[1]);
+ : appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+
+ networkAccessManager = new QNetworkAccessManager(this);
+
+ auto waitingDialog = new WaitingDialog(tr("Loading Gnupg"), this);
+
+ // Init Gnupg
+ auto ctx_thread = QThread::create([&]() { mCtx = new GpgME::GpgContext(); });
+ ctx_thread->start();
+ while (ctx_thread->isRunning())
+ QApplication::processEvents();
+ waitingDialog->close();
+ ctx_thread->deleteLater();
+
+ QString baseUrl = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest";
+
+ QNetworkRequest request;
+ request.setUrl(QUrl(baseUrl));
+
+ QNetworkReply *replay = networkAccessManager->get(request);
+
+ auto version_thread = new VersionCheckThread(replay);
+
+ connect(version_thread, SIGNAL(finished(QPrivateSignal)), version_thread, SLOT(deleteLater()));
+ connect(version_thread, SIGNAL(upgradeVersion(const QString &, const QString &)), this, SLOT(slotVersionUpgrade(const QString &, const QString &)));
+
+ version_thread->start();
+
+ // Check Context Status
+ if (!mCtx->isGood()) {
+ QMessageBox::critical(
+ nullptr, tr("ENV Loading Failed"),
+ tr("Gnupg is not installed correctly, please follow the ReadME "
+ "instructions to install gnupg and then open GPGFrontend."));
+ QCoreApplication::quit();
+ exit(0);
+ }
+
+ /* get path were app was started */
+ setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
+ setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
+
+ edit = new TextEdit(this);
+ setCentralWidget(edit);
+
+ /* the list of Keys available*/
+ mKeyList = new KeyList(mCtx, KeyListRow::SECRET_OR_PUBLIC_KEY,
+ KeyListColumn::TYPE | KeyListColumn::NAME |
+ KeyListColumn::EmailAddress |
+ KeyListColumn::Usage | KeyListColumn::Validity,
+ this);
+ mKeyList->setFilter([](const GpgKey &key) -> bool {
+ if (key.revoked || key.disabled || key.expired)
+ return false;
+ else
+ return true;
+ });
+ mKeyList->slotRefresh();
+
+ infoBoard = new InfoBoardWidget(this, mCtx, mKeyList);
+
+ /* List of binary Attachments */
+ attachmentDockCreated = false;
+
+ /* Variable containing if restart is needed */
+ this->slotSetRestartNeeded(false);
+
+ keyMgmt = new KeyMgmt(mCtx, this);
+ keyMgmt->hide();
+ /* test attachmentdir for files alll 15s */
+ auto *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(slotCheckAttachmentFolder()));
+ timer->start(5000);
+
+ createActions();
+ createMenus();
+ createToolBars();
+ createStatusBar();
+ createDockWindows();
+
+ connect(edit->tabWidget, SIGNAL(currentChanged(int)), this,
+ SLOT(slotDisableTabActions(int)));
+
+ mKeyList->addMenuAction(appendSelectedKeysAct);
+ mKeyList->addMenuAction(copyMailAddressToClipboardAct);
+ mKeyList->addMenuAction(showKeyDetailsAct);
+ mKeyList->addSeparator();
+ mKeyList->addMenuAction(refreshKeysFromKeyserverAct);
+ mKeyList->addMenuAction(uploadKeyToServerAct);
+
+ restoreSettings();
+
+ // open filename if provided as first command line parameter
+ QStringList args = qApp->arguments();
+ if (args.size() > 1) {
+ if (!args[1].startsWith("-")) {
+ if (QFile::exists(args[1]))
+ edit->loadFile(args[1]);
+ }
+ }
+ edit->curTextPage()->setFocus();
+ this->setMinimumSize(1200, 700);
+ this->setWindowTitle(qApp->applicationName());
+ this->show();
+
+ // Show wizard, if the don't show wizard message box wasn't checked
+ // and keylist doesn't contain a private key
+ qDebug() << "wizard/showWizard"
+ << settings.value("wizard/showWizard", true).toBool();
+ qDebug() << "wizard/nextPage" << settings.value("wizard/nextPage").isNull();
+ if (settings.value("wizard/showWizard", true).toBool() ||
+ !settings.value("wizard/nextPage").isNull()) {
+ slotStartWizard();
}
- }
- edit->curTextPage()->setFocus();
- this->setMinimumSize(1200, 700);
- this->setWindowTitle(qApp->applicationName());
- this->show();
-
- // Show wizard, if the don't show wizard message box wasn't checked
- // and keylist doesn't contain a private key
- qDebug() << "wizard/showWizard"
- << settings.value("wizard/showWizard", true).toBool();
- qDebug() << "wizard/nextPage" << settings.value("wizard/nextPage").isNull();
- if (settings.value("wizard/showWizard", true).toBool() ||
- !settings.value("wizard/nextPage").isNull()) {
- slotStartWizard();
- }
}
void MainWindow::restoreSettings() {
- // state sets pos & size of dock-widgets
- this->restoreState(settings.value("window/windowState").toByteArray());
-
- // Restore window size & location
- if (settings.value("window/windowSave").toBool()) {
- QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint();
- QSize size = settings.value("window/size", QSize(800, 450)).toSize();
- this->resize(size);
- this->move(pos);
- } else {
- this->resize(QSize(800, 450));
- this->move(QPoint(100, 100));
- }
-
- // Iconsize
- QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
- this->setIconSize(iconSize);
-
- importButton->setIconSize(iconSize);
- fileEncButton->setIconSize(iconSize);
- // set list of keyserver if not defined
- QStringList *keyServerDefaultList;
- keyServerDefaultList = new QStringList("http://keys.gnupg.net");
- keyServerDefaultList->append("https://keyserver.ubuntu.com");
- keyServerDefaultList->append("http://pool.sks-keyservers.net");
-
- QStringList keyServerList =
- settings.value("keyserver/keyServerList", *keyServerDefaultList)
- .toStringList();
- settings.setValue("keyserver/keyServerList", keyServerList);
-
- // set default keyserver, if it's not set
- QString defaultKeyServer = settings
- .value("keyserver/defaultKeyServer",
- QString("https://keyserver.ubuntu.com"))
- .toString();
- settings.setValue("keyserver/defaultKeyServer", defaultKeyServer);
-
- // Iconstyle
- Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(
- settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
- .toUInt());
- this->setToolButtonStyle(buttonStyle);
- importButton->setToolButtonStyle(buttonStyle);
- fileEncButton->setToolButtonStyle(buttonStyle);
-
- // Checked Keys
- if (settings.value("keys/saveKeyChecked").toBool()) {
- QStringList keyIds =
- settings.value("keys/savedCheckedKeyList").toStringList();
- mKeyList->setChecked(&keyIds);
- }
+ // state sets pos & size of dock-widgets
+ this->restoreState(settings.value("window/windowState").toByteArray());
+
+ // Restore window size & location
+ if (settings.value("window/windowSave").toBool()) {
+ QPoint pos = settings.value("window/pos", QPoint(100, 100)).toPoint();
+ QSize size = settings.value("window/size", QSize(800, 450)).toSize();
+ this->resize(size);
+ this->move(pos);
+ } else {
+ this->resize(QSize(800, 450));
+ this->move(QPoint(100, 100));
+ }
+
+ // Iconsize
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
+ this->setIconSize(iconSize);
+
+ importButton->setIconSize(iconSize);
+ fileEncButton->setIconSize(iconSize);
+ // set list of keyserver if not defined
+ QStringList *keyServerDefaultList;
+ keyServerDefaultList = new QStringList("http://keys.gnupg.net");
+ keyServerDefaultList->append("https://keyserver.ubuntu.com");
+ keyServerDefaultList->append("http://pool.sks-keyservers.net");
+
+ QStringList keyServerList =
+ settings.value("keyserver/keyServerList", *keyServerDefaultList)
+ .toStringList();
+ settings.setValue("keyserver/keyServerList", keyServerList);
+
+ // set default keyserver, if it's not set
+ QString defaultKeyServer = settings
+ .value("keyserver/defaultKeyServer",
+ QString("https://keyserver.ubuntu.com"))
+ .toString();
+ settings.setValue("keyserver/defaultKeyServer", defaultKeyServer);
+
+ // Iconstyle
+ Qt::ToolButtonStyle buttonStyle = static_cast<Qt::ToolButtonStyle>(
+ settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
+ .toUInt());
+ this->setToolButtonStyle(buttonStyle);
+ importButton->setToolButtonStyle(buttonStyle);
+ fileEncButton->setToolButtonStyle(buttonStyle);
+
+ // Checked Keys
+ if (settings.value("keys/saveKeyChecked").toBool()) {
+ QStringList keyIds =
+ settings.value("keys/savedCheckedKeyList").toStringList();
+ mKeyList->setChecked(&keyIds);
+ }
}
void MainWindow::saveSettings() {
- // window position and size
- settings.setValue("window/windowState", saveState());
- settings.setValue("window/pos", pos());
- settings.setValue("window/size", size());
-
- // keyid-list of private checked keys
- if (settings.value("keys/saveKeyChecked").toBool()) {
- QStringList *keyIds = mKeyList->getChecked();
- if (!keyIds->isEmpty()) {
- settings.setValue("keys/savedCheckedKeyList", *keyIds);
+ // window position and size
+ settings.setValue("window/windowState", saveState());
+ settings.setValue("window/pos", pos());
+ settings.setValue("window/size", size());
+
+ // keyid-list of private checked keys
+ if (settings.value("keys/saveKeyChecked").toBool()) {
+ QStringList *keyIds = mKeyList->getChecked();
+ if (!keyIds->isEmpty()) {
+ settings.setValue("keys/savedCheckedKeyList", *keyIds);
+ } else {
+ settings.setValue("keys/savedCheckedKeyList", "");
+ }
} else {
- settings.setValue("keys/savedCheckedKeyList", "");
+ settings.remove("keys/savedCheckedKeyList");
}
- } else {
- settings.remove("keys/savedCheckedKeyList");
- }
}
void MainWindow::closeAttachmentDock() {
- if (!attachmentDockCreated) {
- return;
- }
- attachmentDock->close();
- attachmentDock->deleteLater();
- attachmentDockCreated = false;
+ if (!attachmentDockCreated) {
+ return;
+ }
+ attachmentDock->close();
+ attachmentDock->deleteLater();
+ attachmentDockCreated = false;
}
void MainWindow::closeEvent(QCloseEvent *event) {
- /*
- * ask to save changes, if there are
- * modified documents in any tab
- */
- if (edit->maybeSaveAnyTab()) {
- saveSettings();
- event->accept();
- } else {
- event->ignore();
- }
-
- // clear password from memory
- mCtx->clearPasswordCache();
+ /*
+ * ask to save changes, if there are
+ * modified documents in any tab
+ */
+ if (edit->maybeSaveAnyTab()) {
+ saveSettings();
+ event->accept();
+ } else {
+ event->ignore();
+ }
+
+ // clear password from memory
+ mCtx->clearPasswordCache();
}
diff --git a/src/Mime.cpp b/src/Mime.cpp
deleted file mode 100644
index 8e4c8d72..00000000
--- a/src/Mime.cpp
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-/* TODO: proper import / copyright statement
- *
- */
-
-#include "Mime.h"
-
-Mime::Mime(QByteArray *message) {
- splitParts(message);
- /*
- mMessage = message;
- int bStart = mMessage->indexOf("boundary=\"") + 10 ;
- int bEnd = mMessage->indexOf("\"\n", bStart );
-
- qDebug() << "bStart: " << bStart << " bEnd: " << bEnd;
- mBoundary = new QByteArray(mMessage->mid(bStart, bEnd - bStart));
- qDebug() << "boundary: " << *mBoundary;
-
- Part *p1 = new Part();
-
- int nb = mMessage->indexOf(*mBoundary, bEnd) + mBoundary->length() +1 ;
- qDebug() << "nb: " << nb;
- int eh = mMessage->indexOf("\n\n", nb);
- qDebug() << "eh: " << eh;
- QByteArray *header = new QByteArray(mMessage->mid(nb , eh - nb));
- qDebug() << "header:" << header;
-
- // split header at newlines
- foreach(QByteArray tmp , header->split(* "\n")) {
- // split lines at :
- QList<QByteArray> tmp2 = tmp.split(* ":");
- p1->header.insert(QString(tmp2[0].trimmed()), QString(tmp2[1].trimmed()));
- }
-
- QHashIterator<QString, QString> i(p1->header);
- while (i.hasNext()) {
- i.next();
- qDebug() << "found: " << i.key() << ":" << i.value() << endl;
- }
-
- int nb2 = mMessage->indexOf(*mBoundary, eh);
-
- p1->body = mMessage->mid(eh , nb2 - eh);
-
- QTextCodec *codec = QTextCodec::codecForName("ISO-8859-15");
- QString qs = codec->toUnicode(p1->body);
- qDebug() << "body: " << qs;
- */
-}
-
-Mime::~Mime()
-= default;
-
-void Mime::splitParts(QByteArray *message) {
- int pos1, pos2, headEnd;
- MimePart p_tmp;
-
- // find the boundary
- pos1 = message->indexOf("boundary=\"") + 10;
- pos2 = message->indexOf("\"\n", pos1);
- QByteArray boundary = message->mid(pos1, pos2 - pos1);
- //qDebug() << "boundary: " << boundary;
-
- while (pos2 > pos1) {
-
- pos1 = message->indexOf(boundary, pos2) + boundary.length() + 1;
- headEnd = message->indexOf("\n\n", pos1);
- if (headEnd < 0)
- break;
- QByteArray header = message->mid(pos1, headEnd - pos1);
-
- p_tmp.header = parseHeader(&header);
-
- pos2 = message->indexOf(boundary, headEnd);
- p_tmp.body = message->mid(headEnd, pos2 - headEnd);
-
- mPartList.append(p_tmp);
- }
-}
-
-Header Mime::parseHeader(QByteArray *header) {
-
- QList<HeadElem> ret;
-
- /** http://www.aspnetmime.com/help/welcome/overviewmimeii.html :
- * If a line starts with any white space, that line is said to be 'folded' and is actually
- * part of the header above it.
- */
- header->replace("\n ", " ");
-
- //split header at newlines
- foreach(QByteArray line, header->split(*"\n")) {
- HeadElem elem;
- //split lines at :
- QList<QByteArray> tmp2 = line.split(*":");
- elem.name = tmp2[0].trimmed();
- if (tmp2[1].contains(';')) {
- // split lines at ;
- // TODO: what if ; is inside ""
- QList<QByteArray> tmp3 = tmp2[1].split(*";");
- elem.value = QString(tmp3.takeFirst().trimmed());
- foreach(QByteArray tmp4, tmp3) {
- QList<QByteArray> tmp5 = tmp4.split(*"=");
- elem.params.insert(QString(tmp5[0].trimmed()), QString(tmp5[1].trimmed()));
- }
- } else {
- elem.value = tmp2[1].trimmed();
- }
- ret.append(elem);
- }
- return Header(ret);
-}
-
-Header Mime::getHeader(const QByteArray *message) {
- int headEnd = message->indexOf("\n\n");
- QByteArray header = message->mid(0, headEnd);
- return parseHeader(&header);
-}
-
-bool Mime::isMultipart(QByteArray *message) {
- return message->startsWith("Content-Type: multipart/mixed;");
-}
-
-/**
- * if Content-Type is specified, it should be mime
- *
- */
-bool Mime::isMime(const QByteArray *message) {
- return message->startsWith("Content-Type:");
-}
-
-/***
- * quotedPrintableDecode copied from KCodecs, where it is stated:
-
- The quoted-printable codec as described in RFC 2045, section 6.7. is by
- Rik Hemsley (C) 2001.
-
- */
-
-static const char hexChars[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-/******************************** KCodecs ********************************/
-// strchr(3) for broken systems.
-static int rikFindChar(const char *_s, const char c) {
- const char *s = _s;
-
- while (true) {
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- if ((0 == *s) || (c == *s)) break;
- ++s;
- }
-
- return static_cast<int>(s - _s);
-}
-
-void Mime::quotedPrintableDecode(const QByteArray &in, QByteArray &out) {
- // clear out the output buffer
- out.resize(0);
- if (in.isEmpty())
- return;
-
- char *cursor;
- const char *data;
- const size_t length = in.size();
-
- data = in.data();
- out.resize(static_cast<int>(length));
- cursor = out.data();
-
- for (unsigned int i = 0; i < length; i++) {
- char c(in[i]);
-
- if ('=' == c) {
- if (i < length - 2) {
- char c1 = in[i + 1];
- char c2 = in[i + 2];
-
- if (('\n' == c1) || ('\r' == c1 && '\n' == c2)) {
- // Soft line break. No output.
- if ('\r' == c1)
- i += 2; // CRLF line breaks
- else
- i += 1;
- } else {
- // =XX encoded byte.
-
- int hexChar0 = rikFindChar(hexChars, c1);
- int hexChar1 = rikFindChar(hexChars, c2);
-
- if (hexChar0 < 16 && hexChar1 < 16) {
- *cursor++ = char((hexChar0 * 16) | hexChar1);
- i += 2;
- }
- }
- }
- } else {
- *cursor++ = c;
- }
- }
-
- out.truncate(static_cast<int>(cursor - out.data()));
-}
diff --git a/src/gpg/GpgContext.cpp b/src/gpg/GpgContext.cpp
index e94ce1ab..0462433d 100644
--- a/src/gpg/GpgContext.cpp
+++ b/src/gpg/GpgContext.cpp
@@ -24,8 +24,8 @@
#include "gpg/GpgContext.h"
+#include <functional>
#include <unistd.h> /* contains read/write */
-#include <Mime.h>
#ifdef _WIN32
@@ -73,8 +73,10 @@ namespace GpgME {
<< engineInfo->home_dir << engineInfo->version;
if (engineInfo->protocol == GPGME_PROTOCOL_GPGCONF && strcmp(engineInfo->version, "1.0.0") != 0)
find_gpgconf = true;
- if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && strcmp(engineInfo->version, "1.0.0") != 0)
+ if (engineInfo->protocol == GPGME_PROTOCOL_OpenPGP && strcmp(engineInfo->version, "1.0.0") != 0) {
+ gpgExec = engineInfo->file_name;
find_openpgp = true;
+ }
if (engineInfo->protocol == GPGME_PROTOCOL_CMS && strcmp(engineInfo->version, "1.0.0") != 0)
find_cms = true;
if (engineInfo->protocol == GPGME_PROTOCOL_ASSUAN)
@@ -430,38 +432,6 @@ namespace GpgME {
return err;
}
-
- /**
- * if this is mime, split text and attachments...
- * message contains only text afterwards
- */
- void parseMime(QByteArray *message) {
-
- QString pText;
- bool show_ma_dock = false;
-
- Mime *mime = new Mime(message);
- for (MimePart tmp : mime->parts()) {
- if (tmp.header.getValue("Content-Type") == "text/plain" &&
- tmp.header.getValue("Content-Transfer-Encoding") != "base64") {
- QByteArray body;
- if (tmp.header.getValue("Content-Transfer-Encoding") == "quoted-printable") {
- Mime::quotedPrintableDecode(tmp.body, body);
- } else {
- body = tmp.body;
- }
- pText.append(QString(body));
- } else {
- // TODO
- show_ma_dock = true;
- }
- }
- *message = pText.toUtf8();
- if (show_ma_dock) {
- // TODO
- }
- }
-
/** Decrypt QByteAarray, return QByteArray
* mainly from http://basket.kde.org/ (kgpgme.cpp)
*/
@@ -496,28 +466,6 @@ namespace GpgME {
gpgme_data_release(dataOut);
}
- /*
- * 1) is it mime (content-type:)
- * 2) parse header
- * 2) choose action depending on content-type
- */
- if (Mime::isMime(outBuffer)) {
- Header header = Mime::getHeader(outBuffer);
- // is it multipart, is multipart-parsing enabled
- if (header.getValue("Content-Type") == "multipart/mixed"
- && settings.value("mime/parseMime").toBool()) {
- parseMime(outBuffer);
- } else if (header.getValue("Content-Type") == "text/plain"
- && settings.value("mime/parseQP").toBool()) {
- if (header.getValue("Content-Transfer-Encoding") == "quoted-printable") {
- auto *decoded = new QByteArray();
- Mime::quotedPrintableDecode(*outBuffer, *decoded);
- //TODO: remove header
- outBuffer = decoded;
- }
- }
- }
-
if (result != nullptr) {
*result = m_result;
}
@@ -659,16 +607,16 @@ namespace GpgME {
bool GpgContext::exportSecretKey(const GpgKey &key, QByteArray *outBuffer) {
qDebug() << "Export Secret Key" << key.id;
gpgme_key_t target_key[2] = {
- key.key_refer,
- nullptr
+ key.key_refer,
+ nullptr
};
gpgme_data_t dataOut;
gpgme_data_new(&dataOut);
// export private key to outBuffer
- gpgme_error_t error = gpgme_op_export_keys(mCtx, target_key,GPGME_EXPORT_MODE_SECRET, dataOut);
+ gpgme_error_t error = gpgme_op_export_keys(mCtx, target_key, GPGME_EXPORT_MODE_SECRET, dataOut);
- if(gpgme_err_code(error) != GPG_ERR_NO_ERROR) {
+ if (gpgme_err_code(error) != GPG_ERR_NO_ERROR) {
checkErr(error);
gpgme_data_release(dataOut);
return false;
@@ -680,20 +628,31 @@ namespace GpgME {
}
/** return type should be gpgme_error_t*/
- void GpgContext::executeGpgCommand(const QStringList &arguments, QByteArray *stdOut, QByteArray *stdErr) {
+ QProcess * GpgContext::executeGpgCommand(const QStringList &arguments, QByteArray *stdOut, QByteArray *stdErr,
+ const std::function<void(QProcess *)> &interactFunc) {
QStringList args;
- args << "--homedir" << gpgKeys << "--batch" << arguments;
+ args << arguments;
+
+ auto *gpgProcess = new QProcess(this);
+ qDebug() << "gpgExec" << gpgExec << args;
+
+ gpgProcess->setReadChannel(QProcess::StandardOutput);
+ connect(gpgProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
+ gpgProcess, SLOT(deleteLater()));
+ connect(gpgProcess, &QProcess::readyReadStandardOutput, this, [gpgProcess, interactFunc]() {
+ qDebug() << "Function Called" << &gpgProcess;
+ // interactFunc(gpgProcess);
+ });
- qDebug() << args;
- QProcess gpg;
- // qDebug() << "engine->file_name" << engine->file_name;
+ gpgProcess->start(gpgExec, args);
- gpg.start(gpgBin, args);
- gpg.waitForFinished();
+ if (gpgProcess->waitForStarted()){
+ qDebug() << "Gpg Process Started Success";
+ } else {
+ qDebug() << "Gpg Process Started Failed";
+ }
- *stdOut = gpg.readAllStandardOutput();
- *stdErr = gpg.readAllStandardError();
- qDebug() << *stdOut;
+ return gpgProcess;
}
/***
@@ -734,26 +693,6 @@ namespace GpgME {
return gpgmeError;
}
- /***
- * return type should contain:
- * -> list of sigs
- * -> valid
- * -> decrypted message
- */
- //void GpgContext::decryptVerify(QByteArray in) {
-
- /* gpgme_error_t err;
- gpgme_data_t in, out;
-
- gpgme_decrypt_result_t decrypt_result;
- gpgme_verify_result_t verify_result;
-
- err = gpgme_op_decrypt_verify (mCtx, in, out);
- decrypt_result = gpgme_op_decrypt_result (mCtx);
-
- verify_result = gpgme_op_verify_result (mCtx);
- */
- //}
gpg_error_t
GpgContext::sign(const QVector<GpgKey> &keys, const QByteArray &inBuffer, QByteArray *outBuffer, bool detached,
gpgme_sign_result_t *result) {
@@ -962,7 +901,7 @@ namespace GpgME {
void GpgContext::setSigners(const QVector<GpgKey> &keys) {
gpgme_signers_clear(mCtx);
for (const auto &key : keys) {
- if(checkIfKeyCanSign(key)) {
+ if (checkIfKeyCanSign(key)) {
auto gpgmeError = gpgme_signers_add(mCtx, key.key_refer);
checkErr(gpgmeError);
}
@@ -1180,7 +1119,7 @@ namespace GpgME {
}
}
- if(gpgme_err_code(err) != GPG_ERR_NO_ERROR)
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR)
checkErr(err);
if (dataIn) {
@@ -1240,11 +1179,11 @@ namespace GpgME {
return false;
}
- for (const auto& key : keys) {
+ for (const auto &key : keys) {
err = gpgme_data_new(&dataOut);
checkErr(err);
- err = gpgme_op_export(mCtx,key.id.toUtf8().constData(), 0, dataOut);
+ err = gpgme_op_export(mCtx, key.id.toUtf8().constData(), 0, dataOut);
checkErr(err);
read_bytes = gpgme_data_seek(dataOut, 0, SEEK_END);
@@ -1255,4 +1194,41 @@ namespace GpgME {
}
return true;
}
+
+ QProcess * GpgContext::generateRevokeCert(const GpgKey &key, const QString &outputFileName) {
+ QByteArray out, stdErr;
+ auto process = executeGpgCommand({
+ "--command-fd",
+ "0",
+ "--status-fd", "1",
+ "-o",
+ outputFileName,
+ "--gen-revoke",
+ key.fpr
+ }, &out, &stdErr,
+ [](QProcess *proc) {
+ qDebug() << "Function Called" << proc;
+ while (proc->canReadLine()) {
+ const QString line = QString::fromUtf8(proc->readLine()).trimmed();
+ // Command-fd is a stable interface, while this is all kind of hacky we
+ // are on a deadline :-/
+ if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) {
+ proc->write("y\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_LINE ask_revocation_reason.code")) {
+ proc->write("0\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_LINE ask_revocation_reason.text")) {
+ proc->write("\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_BOOL openfile.overwrite.okay")) {
+ // We asked before
+ proc->write("y\n");
+ } else if (line == QLatin1String("[GNUPG:] GET_BOOL ask_revocation_reason.okay")) {
+ proc->write("y\n");
+ }
+ }
+ });
+
+ qDebug() << "GenerateRevokeCert Process" << process;
+
+ return process;
+ }
}
diff --git a/src/main.cpp b/src/main.cpp
index 00ab2738..ff3b0bb4 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -23,6 +23,7 @@
*/
#include "MainWindow.h"
+#include "GpgFrontendBuildInfo.h"
int main(int argc, char *argv[]) {
@@ -61,7 +62,7 @@ int main(int argc, char *argv[]) {
QTranslator translator, translator2;
int return_from_event_loop_code;
- qDebug() << settings.fileName();
+ qDebug() << "Resource Directory" << RESOURCE_DIR(appPath);
do {
QApplication::removeTranslator(&translator);
diff --git a/src/smtp/CMakeLists.txt b/src/smtp/CMakeLists.txt
new file mode 100644
index 00000000..8e341f98
--- /dev/null
+++ b/src/smtp/CMakeLists.txt
@@ -0,0 +1,6 @@
+aux_source_directory(. SMTP_MIME_SOURCE)
+
+add_library(smtp STATIC ${SMTP_MIME_SOURCE})
+
+target_link_libraries(smtp
+ Qt5::Network Qt5::Core)
diff --git a/src/smtp/emailaddress.cpp b/src/smtp/emailaddress.cpp
new file mode 100644
index 00000000..c0ecaa0d
--- /dev/null
+++ b/src/smtp/emailaddress.cpp
@@ -0,0 +1,44 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/emailaddress.h"
+
+/* [1] Constructors and Destructors */
+
+EmailAddress::EmailAddress(const QString &address, const QString &name) {
+ this->address = address;
+ this->name = name;
+}
+
+EmailAddress::~EmailAddress() {}
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void EmailAddress::setName(const QString &name) { this->name = name; }
+
+void EmailAddress::setAddress(const QString &address) {
+ this->address = address;
+}
+
+const QString &EmailAddress::getName() const { return name; }
+
+const QString &EmailAddress::getAddress() const { return address; }
+
+/* [2] --- */
diff --git a/src/smtp/mimeattachment.cpp b/src/smtp/mimeattachment.cpp
new file mode 100644
index 00000000..033eecfb
--- /dev/null
+++ b/src/smtp/mimeattachment.cpp
@@ -0,0 +1,43 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimeattachment.h"
+#include <QFileInfo>
+
+/* [1] Constructors and Destructors */
+
+MimeAttachment::MimeAttachment(QFile *file) : MimeFile(file) {}
+
+MimeAttachment::MimeAttachment(const QByteArray &stream,
+ const QString &fileName)
+ : MimeFile(stream, fileName) {}
+
+MimeAttachment::~MimeAttachment() = default;
+
+/* [1] --- */
+
+/* [2] Protected methods */
+
+void MimeAttachment::prepare() {
+ this->header += "Content-disposition: attachment\r\n";
+
+ /* !!! IMPORTANT !!! */
+ MimeFile::prepare();
+}
+
+/* [2] --- */
diff --git a/src/smtp/mimecontentformatter.cpp b/src/smtp/mimecontentformatter.cpp
new file mode 100644
index 00000000..8f538457
--- /dev/null
+++ b/src/smtp/mimecontentformatter.cpp
@@ -0,0 +1,59 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimecontentformatter.h"
+
+MimeContentFormatter::MimeContentFormatter(int max_length)
+ : max_length(max_length) {}
+
+QString MimeContentFormatter::format(const QString &content,
+ bool quotedPrintable) const {
+
+ QString out;
+
+ int chars = 0;
+ for (auto i : content) {
+ chars++;
+ if (!quotedPrintable) {
+ if (chars > max_length) {
+ out.append("\r\n");
+ chars = 1;
+ }
+ } else {
+ if (i == '\n') { // new line
+ out.append(i);
+ chars = 0;
+ continue;
+ }
+
+ if ((chars > max_length - 1) ||
+ ((i == '=') && (chars > max_length - 3))) {
+ out.append('=');
+ out.append("\r\n");
+ chars = 1;
+ }
+ }
+ out.append(i);
+ }
+
+ return out;
+}
+
+void MimeContentFormatter::setMaxLength(int l) { max_length = l; }
+
+int MimeContentFormatter::getMaxLength() const { return max_length; }
diff --git a/src/smtp/mimefile.cpp b/src/smtp/mimefile.cpp
new file mode 100644
index 00000000..4f095b84
--- /dev/null
+++ b/src/smtp/mimefile.cpp
@@ -0,0 +1,61 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimefile.h"
+#include <QFileInfo>
+
+/* [1] Constructors and Destructors */
+
+MimeFile::MimeFile(QFile *file) {
+ this->file = file;
+ this->cType = "application/octet-stream";
+ this->cName = QFileInfo(*file).fileName();
+ this->cEncoding = Base64;
+}
+
+MimeFile::MimeFile(const QByteArray &stream, const QString &fileName) {
+ this->cEncoding = Base64;
+ this->cType = "application/octet-stream";
+ this->file = nullptr;
+ this->cName = fileName;
+ this->content = stream;
+}
+
+MimeFile::~MimeFile() {
+ delete file;
+}
+
+/* [1] --- */
+
+/* [2] Getters and setters */
+
+/* [2] --- */
+
+/* [3] Protected methods */
+
+void MimeFile::prepare() {
+ if (this->file) {
+ file->open(QIODevice::ReadOnly);
+ this->content = file->readAll();
+ file->close();
+ }
+ /* !!! IMPORTANT !!!! */
+ MimePart::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimehtml.cpp b/src/smtp/mimehtml.cpp
new file mode 100644
index 00000000..9f3a53c3
--- /dev/null
+++ b/src/smtp/mimehtml.cpp
@@ -0,0 +1,46 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimehtml.h"
+
+/* [1] Constructors and Destructors */
+
+MimeHtml::MimeHtml(const QString &html) : MimeText(html) {
+ this->cType = "text/html";
+}
+
+MimeHtml::~MimeHtml() = default;
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void MimeHtml::setHtml(const QString &html) { this->text = html; }
+
+const QString &MimeHtml::getHtml() const { return text; }
+
+/* [2] --- */
+
+/* [3] Protected methods */
+
+void MimeHtml::prepare() {
+ /* !!! IMPORTANT !!! */
+ MimeText::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimeinlinefile.cpp b/src/smtp/mimeinlinefile.cpp
new file mode 100644
index 00000000..a49167e8
--- /dev/null
+++ b/src/smtp/mimeinlinefile.cpp
@@ -0,0 +1,42 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimeinlinefile.h"
+
+/* [1] Constructors and Destructors */
+
+MimeInlineFile::MimeInlineFile(QFile *f) : MimeFile(f) {}
+
+MimeInlineFile::~MimeInlineFile() = default;
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+/* [2] --- */
+
+/* [3] Protected methods */
+
+void MimeInlineFile::prepare() {
+ this->header += "Content-Disposition: inline\r\n";
+
+ /* !!! IMPORTANT !!! */
+ MimeFile::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimemessage.cpp b/src/smtp/mimemessage.cpp
new file mode 100644
index 00000000..cf653e0a
--- /dev/null
+++ b/src/smtp/mimemessage.cpp
@@ -0,0 +1,308 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimemessage.h"
+#include "smtp/quotedprintable.h"
+
+#include <QDateTime>
+#include <QLocale>
+#include <typeinfo>
+
+/* [1] Constructors and Destructors */
+MimeMessage::MimeMessage(bool createAutoMimeContent)
+ : replyTo(nullptr), hEncoding(MimePart::_8Bit) {
+ if (createAutoMimeContent)
+ this->content = new MimeMultiPart();
+
+ autoMimeContentCreated = createAutoMimeContent;
+}
+
+MimeMessage::~MimeMessage() {
+ if (this->autoMimeContentCreated) {
+ this->autoMimeContentCreated = false;
+ delete (this->content);
+ }
+}
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+MimePart &MimeMessage::getContent() { return *content; }
+
+void MimeMessage::setContent(MimePart *content) {
+ if (this->autoMimeContentCreated) {
+ this->autoMimeContentCreated = false;
+ delete (this->content);
+ }
+ this->content = content;
+}
+
+void MimeMessage::setReplyTo(EmailAddress *rto) { replyTo = rto; }
+
+void MimeMessage::setSender(EmailAddress *e) {
+ this->sender = e;
+ e->setParent(this);
+}
+
+void MimeMessage::addRecipient(EmailAddress *rcpt, RecipientType type) {
+ switch (type) {
+ case To:
+ recipientsTo << rcpt;
+ break;
+ case Cc:
+ recipientsCc << rcpt;
+ break;
+ case Bcc:
+ recipientsBcc << rcpt;
+ break;
+ }
+
+ rcpt->setParent(this);
+}
+
+void MimeMessage::addTo(EmailAddress *rcpt) { this->recipientsTo << rcpt; }
+
+void MimeMessage::addCc(EmailAddress *rcpt) { this->recipientsCc << rcpt; }
+
+void MimeMessage::addBcc(EmailAddress *rcpt) { this->recipientsBcc << rcpt; }
+
+void MimeMessage::setSubject(const QString &subject) {
+ this->subject = subject;
+}
+
+void MimeMessage::addPart(MimePart *part) {
+ if (typeid(*content) == typeid(MimeMultiPart)) {
+ ((MimeMultiPart *) content)->addPart(part);
+ };
+}
+
+void MimeMessage::setInReplyTo(const QString &inReplyTo) {
+ mInReplyTo = inReplyTo;
+}
+
+void MimeMessage::setHeaderEncoding(MimePart::Encoding hEnc) {
+ this->hEncoding = hEnc;
+}
+
+const EmailAddress &MimeMessage::getSender() const { return *sender; }
+
+const QList<EmailAddress *> &
+MimeMessage::getRecipients(RecipientType type) const {
+ switch (type) {
+ default:
+ case To:
+ return recipientsTo;
+ case Cc:
+ return recipientsCc;
+ case Bcc:
+ return recipientsBcc;
+ }
+}
+
+const EmailAddress *MimeMessage::getReplyTo() const { return replyTo; }
+
+const QString &MimeMessage::getSubject() const { return subject; }
+
+const QList<MimePart *> &MimeMessage::getParts() const {
+ if (typeid(*content) == typeid(MimeMultiPart)) {
+ return ((MimeMultiPart *) content)->getParts();
+ } else {
+ auto *res = new QList<MimePart *>();
+ res->append(content);
+ return *res;
+ }
+}
+
+/* [2] --- */
+
+/* [3] Public Methods */
+
+QString MimeMessage::toString() {
+ QString mime;
+
+ /* =========== MIME HEADER ============ */
+
+ /* ---------- Sender / From ----------- */
+ mime = "From:";
+ if (sender->getName() != "") {
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += " =?utf-8?B?" +
+ QByteArray().append(sender->getName().toUtf8()).toBase64() + "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(
+ QByteArray().append(sender->getName().toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += " " + sender->getName();
+ }
+ }
+ mime += " <" + sender->getAddress() + ">\r\n";
+ /* ---------------------------------- */
+
+ /* ------- Recipients / To ---------- */
+ mime += "To:";
+ QList<EmailAddress *>::iterator it;
+ int i;
+ for (i = 0, it = recipientsTo.begin(); it != recipientsTo.end(); ++it, ++i) {
+ if (i != 0) {
+ mime += ",";
+ }
+
+ if ((*it)->getName() != "") {
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += " =?utf-8?B?" +
+ QByteArray().append((*it)->getName().toUtf8()).toBase64() +
+ "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(
+ QByteArray().append((*it)->getName().toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += " " + (*it)->getName();
+ }
+ }
+ mime += " <" + (*it)->getAddress() + ">";
+ }
+ mime += "\r\n";
+ /* ---------------------------------- */
+
+ /* ------- Recipients / Cc ---------- */
+ if (!recipientsCc.empty()) {
+ mime += "Cc:";
+ }
+ for (i = 0, it = recipientsCc.begin(); it != recipientsCc.end(); ++it, ++i) {
+ if (i != 0) {
+ mime += ",";
+ }
+
+ if ((*it)->getName() != "") {
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += " =?utf-8?B?" +
+ QByteArray().append((*it)->getName().toUtf8()).toBase64() +
+ "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(
+ QByteArray().append((*it)->getName().toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += " " + (*it)->getName();
+ }
+ }
+ mime += " <" + (*it)->getAddress() + ">";
+ }
+ if (!recipientsCc.empty()) {
+ mime += "\r\n";
+ }
+ /* ---------------------------------- */
+
+ /* ------------ Subject ------------- */
+ mime += "Subject: ";
+
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += "=?utf-8?B?" + QByteArray().append(subject.toUtf8()).toBase64() + "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += "=?utf-8?Q?" +
+ QuotedPrintable::encode(QByteArray().append(subject.toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += subject;
+ }
+ mime += "\r\n";
+ /* ---------------------------------- */
+
+ /* ---------- Reply-To -------------- */
+ if (replyTo) {
+ mime += "Reply-To: ";
+ if (replyTo->getName() != "") {
+ switch (hEncoding) {
+ case MimePart::Base64:
+ mime += " =?utf-8?B?" +
+ QByteArray().append(replyTo->getName().toUtf8()).toBase64() + "?=";
+ break;
+ case MimePart::QuotedPrintable:
+ mime += " =?utf-8?Q?" +
+ QuotedPrintable::encode(QByteArray().append(replyTo->getName().toUtf8()))
+ .replace(' ', "_")
+ .replace(':', "=3A") +
+ "?=";
+ break;
+ default:
+ mime += " " + replyTo->getName();
+ }
+ }
+ mime += " <" + replyTo->getAddress() + ">\r\n";
+ }
+
+ /* ---------------------------------- */
+
+ mime += "MIME-Version: 1.0\r\n";
+ if (!mInReplyTo.isEmpty()) {
+ mime += "In-Reply-To: <" + mInReplyTo + ">\r\n";
+ mime += "References: <" + mInReplyTo + ">\r\n";
+ }
+
+ QDateTime now = QDateTime::currentDateTime();
+#if QT_VERSION_MAJOR < 5 // Qt4 workaround since RFC2822Date isn't defined
+ QString shortDayName =
+ QLocale::c().dayName(now.date().dayOfWeek(), QLocale::ShortFormat);
+ QString shortMonthName =
+ QLocale::c().monthName(now.date().month(), QLocale::ShortFormat);
+ int utcOffset = now.secsTo(QDateTime(now.date(), now.time(), Qt::UTC)) / 60;
+ char timezoneSign = utcOffset >= 0 ? '+' : '-';
+ utcOffset = utcOffset >= 0 ? utcOffset : -utcOffset;
+ QString timezone = QString("%1%2%3")
+ .arg(timezoneSign)
+ .arg(utcOffset / 60, 2, 10, QChar('0'))
+ .arg(utcOffset % 60, 2, 10, QChar('0'));
+ mime += QString("Date: %1\r\n")
+ .arg(now.toString("%1, dd %2 yyyy hh:mm:ss %3")
+ .arg(shortDayName)
+ .arg(shortMonthName)
+ .arg(timezone));
+#else // Qt5 supported
+ mime += QString("Date: %1\r\n").arg(now.toString(Qt::RFC2822Date));
+#endif // support RFC2822Date
+
+ mime += content->toString();
+ return mime;
+}
+
+/* [3] --- */
diff --git a/src/smtp/mimemultipart.cpp b/src/smtp/mimemultipart.cpp
new file mode 100644
index 00000000..14a813c2
--- /dev/null
+++ b/src/smtp/mimemultipart.cpp
@@ -0,0 +1,70 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimemultipart.h"
+#include <QCryptographicHash>
+#include <QRandomGenerator>
+#include <QTime>
+
+const QString MULTI_PART_NAMES[] = {
+ "multipart/mixed", // Mixed
+ "multipart/digest", // Digest
+ "multipart/alternative", // Alternative
+ "multipart/related", // Related
+ "multipart/report", // Report
+ "multipart/signed", // Signed
+ "multipart/encrypted" // Encrypted
+};
+
+MimeMultiPart::MimeMultiPart(MultiPartType type) {
+ this->type = type;
+ this->cType = MULTI_PART_NAMES[this->type];
+ this->cEncoding = _8Bit;
+
+ QRandomGenerator generator;
+
+ QCryptographicHash md5(QCryptographicHash::Md5);
+ md5.addData(QByteArray().append((char) generator.generate()));
+ cBoundary = md5.result().toHex();
+}
+
+void MimeMultiPart::addPart(MimePart *part) { parts.append(part); }
+
+const QList<MimePart *> &MimeMultiPart::getParts() const { return parts; }
+
+void MimeMultiPart::prepare() {
+ QList<MimePart *>::iterator it;
+
+ content = "";
+ for (it = parts.begin(); it != parts.end(); it++) {
+ content += QString("--" + cBoundary + "\r\n").toUtf8();
+ (*it)->prepare();
+ content += (*it)->toString().toUtf8();
+ };
+
+ content += QString("--" + cBoundary + "--\r\n").toUtf8();
+
+ MimePart::prepare();
+}
+
+void MimeMultiPart::setMimeType(const MultiPartType type) {
+ this->type = type;
+ this->cType = MULTI_PART_NAMES[type];
+}
+
+MimeMultiPart::MultiPartType MimeMultiPart::getMimeType() const { return type; }
diff --git a/src/smtp/mimepart.cpp b/src/smtp/mimepart.cpp
new file mode 100644
index 00000000..5d33884d
--- /dev/null
+++ b/src/smtp/mimepart.cpp
@@ -0,0 +1,159 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimepart.h"
+#include "smtp/quotedprintable.h"
+
+/* [1] Constructors and Destructors */
+
+MimePart::MimePart() {
+ cEncoding = _7Bit;
+ prepared = false;
+ cBoundary = "";
+}
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void MimePart::setContent(const QByteArray &content) {
+ this->content = content;
+}
+
+void MimePart::setHeader(const QString &header) { this->header = header; }
+
+void MimePart::addHeaderLine(const QString &line) {
+ this->header += line + "\r\n";
+}
+
+const QString &MimePart::getHeader() const { return header; }
+
+const QByteArray &MimePart::getContent() const { return content; }
+
+void MimePart::setContentId(const QString &cId) { this->cId = cId; }
+
+const QString &MimePart::getContentId() const { return this->cId; }
+
+void MimePart::setContentName(const QString &cName) { this->cName = cName; }
+
+const QString &MimePart::getContentName() const { return this->cName; }
+
+void MimePart::setContentType(const QString &cType) { this->cType = cType; }
+
+const QString &MimePart::getContentType() const { return this->cType; }
+
+void MimePart::setCharset(const QString &charset) { this->cCharset = charset; }
+
+const QString &MimePart::getCharset() const { return this->cCharset; }
+
+void MimePart::setEncoding(Encoding enc) { this->cEncoding = enc; }
+
+MimePart::Encoding MimePart::getEncoding() const { return this->cEncoding; }
+
+MimeContentFormatter &MimePart::getContentFormatter() {
+ return this->formatter;
+}
+
+/* [2] --- */
+
+/* [3] Public methods */
+
+QString MimePart::toString() {
+ if (!prepared)
+ prepare();
+
+ return mimeString;
+}
+
+/* [3] --- */
+
+/* [4] Protected methods */
+
+void MimePart::prepare() {
+ mimeString = QString();
+
+ /* === Header Prepare === */
+
+ /* Content-Type */
+ mimeString.append("Content-Type: ").append(cType);
+
+ if (cName != "")
+ mimeString.append("; name=\"").append(cName).append("\"");
+
+ if (cCharset != "")
+ mimeString.append("; charset=").append(cCharset);
+
+ if (cBoundary != "")
+ mimeString.append("; boundary=").append(cBoundary);
+
+ mimeString.append("\r\n");
+ /* ------------ */
+
+ /* Content-Transfer-Encoding */
+ mimeString.append("Content-Transfer-Encoding: ");
+ switch (cEncoding) {
+ case _7Bit:
+ mimeString.append("7bit\r\n");
+ break;
+ case _8Bit:
+ mimeString.append("8bit\r\n");
+ break;
+ case Base64:
+ mimeString.append("base64\r\n");
+ break;
+ case QuotedPrintable:
+ mimeString.append("quoted-printable\r\n");
+ break;
+ }
+ /* ------------------------ */
+
+ /* Content-Id */
+ if (cId != NULL)
+ mimeString.append("Content-ID: <").append(cId).append(">\r\n");
+ /* ---------- */
+
+ /* Addition header lines */
+
+ mimeString.append(header).append("\r\n");
+
+ /* ------------------------- */
+
+ /* === End of Header Prepare === */
+
+ /* === Content === */
+ switch (cEncoding) {
+ case _7Bit:
+ mimeString.append(QString(content).toLatin1());
+ break;
+ case _8Bit:
+ mimeString.append(content);
+ break;
+ case Base64:
+ mimeString.append(formatter.format(content.toBase64()));
+ break;
+ case QuotedPrintable:
+ mimeString.append(formatter.format(QuotedPrintable::encode(content), true));
+ break;
+ }
+ mimeString.append("\r\n");
+ /* === End of Content === */
+
+ prepared = true;
+}
+
+/* [4] --- */
diff --git a/src/smtp/mimetext.cpp b/src/smtp/mimetext.cpp
new file mode 100644
index 00000000..3726647e
--- /dev/null
+++ b/src/smtp/mimetext.cpp
@@ -0,0 +1,52 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/mimetext.h"
+
+/* [1] Constructors and Destructors */
+
+MimeText::MimeText(const QString &txt) {
+ this->text = txt;
+ this->cType = "text/plain";
+ this->cCharset = "utf-8";
+ this->cEncoding = _8Bit;
+}
+
+MimeText::~MimeText() = default;
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void MimeText::setText(const QString &text) { this->text = text; }
+
+const QString &MimeText::getText() const { return text; }
+
+/* [2] --- */
+
+/* [3] Protected Methods */
+
+void MimeText::prepare() {
+ this->content.clear();
+ this->content.append(text.toUtf8());
+
+ /* !!! IMPORTANT !!! */
+ MimePart::prepare();
+}
+
+/* [3] --- */
diff --git a/src/smtp/quotedprintable.cpp b/src/smtp/quotedprintable.cpp
new file mode 100644
index 00000000..93e51122
--- /dev/null
+++ b/src/smtp/quotedprintable.cpp
@@ -0,0 +1,62 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/quotedprintable.h"
+
+QString QuotedPrintable::encode(const QByteArray &input) {
+ QString output;
+
+ char byte;
+ const char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ for (char i : input) {
+ byte = i;
+
+ if ((byte == 0x20) || ((byte >= 33) && (byte <= 126) && (byte != 61))) {
+ output.append(byte);
+ } else {
+ output.append('=');
+ output.append(hex[((byte >> 4) & 0x0F)]);
+ output.append(hex[(byte & 0x0F)]);
+ }
+ }
+
+ return output;
+}
+
+QByteArray QuotedPrintable::decode(const QString &input) {
+ // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B
+ // C D E F
+ const int hexVal[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0,
+ 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
+
+ QByteArray output;
+
+ for (int i = 0; i < input.length(); ++i) {
+ if (input.at(i).toLatin1() == '=') {
+ output.append((hexVal[input.at(i + 1).toLatin1() - '0'] << 4) +
+ hexVal[input.at(i + 2).toLatin1() - '0']);
+ i += 2;
+ } else {
+ output.append(input.at(i).toLatin1());
+ }
+ }
+
+ return output;
+}
diff --git a/src/smtp/smtpclient.cpp b/src/smtp/smtpclient.cpp
new file mode 100644
index 00000000..63202998
--- /dev/null
+++ b/src/smtp/smtpclient.cpp
@@ -0,0 +1,407 @@
+/*
+ Copyright (c) 2011-2012 - Tőkés Attila
+
+ This file is part of SmtpClient for Qt.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ See the LICENSE file for more details.
+*/
+
+#include "smtp/smtpclient.h"
+
+#include <QByteArray>
+#include <QFileInfo>
+
+/* [1] Constructors and destructors */
+
+SmtpClient::SmtpClient(const QString &host, int port,
+ ConnectionType connectionType)
+ : socket(NULL), name("localhost"), authMethod(AuthPlain),
+ connectionTimeout(5000), responseTimeout(5000),
+ sendMessageTimeout(60000) {
+ setConnectionType(connectionType);
+
+ this->host = host;
+ this->port = port;
+
+ connect(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this,
+ SLOT(socketStateChanged(QAbstractSocket::SocketState)));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this,
+ SLOT(socketError(QAbstractSocket::SocketError)));
+ connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
+}
+
+SmtpClient::~SmtpClient() {
+ if (socket)
+ delete socket;
+}
+
+/* [1] --- */
+
+/* [2] Getters and Setters */
+
+void SmtpClient::setUser(const QString &user) { this->user = user; }
+
+void SmtpClient::setPassword(const QString &password) {
+ this->password = password;
+}
+
+void SmtpClient::setAuthMethod(AuthMethod method) { this->authMethod = method; }
+
+void SmtpClient::setHost(const QString &host) { this->host = host; }
+
+void SmtpClient::setPort(int port) { this->port = port; }
+
+void SmtpClient::setConnectionType(ConnectionType ct) {
+ this->connectionType = ct;
+
+ if (socket)
+ delete socket;
+
+ switch (connectionType) {
+ case TcpConnection:
+ socket = new QTcpSocket(this);
+ break;
+ case SslConnection:
+ case TlsConnection:
+ socket = new QSslSocket(this);
+ }
+}
+
+const QString &SmtpClient::getHost() const { return this->host; }
+
+const QString &SmtpClient::getUser() const { return this->user; }
+
+const QString &SmtpClient::getPassword() const { return this->password; }
+
+SmtpClient::AuthMethod SmtpClient::getAuthMethod() const {
+ return this->authMethod;
+}
+
+int SmtpClient::getPort() const { return this->port; }
+
+SmtpClient::ConnectionType SmtpClient::getConnectionType() const {
+ return connectionType;
+}
+
+const QString &SmtpClient::getName() const { return this->name; }
+
+void SmtpClient::setName(const QString &name) { this->name = name; }
+
+const QString &SmtpClient::getResponseText() const { return responseText; }
+
+int SmtpClient::getResponseCode() const { return responseCode; }
+
+QTcpSocket *SmtpClient::getSocket() { return socket; }
+
+int SmtpClient::getConnectionTimeout() const { return connectionTimeout; }
+
+void SmtpClient::setConnectionTimeout(int msec) { connectionTimeout = msec; }
+
+int SmtpClient::getResponseTimeout() const { return responseTimeout; }
+
+void SmtpClient::setResponseTimeout(int msec) { responseTimeout = msec; }
+
+int SmtpClient::getSendMessageTimeout() const { return sendMessageTimeout; }
+
+void SmtpClient::setSendMessageTimeout(int msec) { sendMessageTimeout = msec; }
+
+/* [2] --- */
+
+/* [3] Public methods */
+
+bool SmtpClient::connectToHost() {
+ switch (connectionType) {
+ case TlsConnection:
+ case TcpConnection:
+ socket->connectToHost(host, port);
+ break;
+ case SslConnection:
+ ((QSslSocket *) socket)->connectToHostEncrypted(host, port);
+ break;
+ }
+
+ // Tries to connect to server
+ if (!socket->waitForConnected(connectionTimeout)) {
+ emit smtpError(ConnectionTimeoutError);
+ return false;
+ }
+
+ try {
+ // Wait for the server's response
+ waitForResponse();
+
+ // If the response code is not 220 (Service ready)
+ // means that is something wrong with the server
+ if (responseCode != 220) {
+ emit smtpError(ServerError);
+ return false;
+ }
+
+ // Send a EHLO/HELO message to the server
+ // The client's first command must be EHLO/HELO
+ sendMessage("EHLO " + name);
+
+ // Wait for the server's response
+ waitForResponse();
+
+ // The response code needs to be 250.
+ if (responseCode != 250) {
+ emit smtpError(ServerError);
+ return false;
+ }
+
+ if (connectionType == TlsConnection) {
+ // send a request to start TLS handshake
+ sendMessage("STARTTLS");
+
+ // Wait for the server's response
+ waitForResponse();
+
+ // The response code needs to be 220.
+ if (responseCode != 220) {
+ emit smtpError(ServerError);
+ return false;
+ };
+
+ ((QSslSocket *) socket)->startClientEncryption();
+
+ if (!((QSslSocket *) socket)->waitForEncrypted(connectionTimeout)) {
+ qDebug() << ((QSslSocket *) socket)->errorString();
+ emit smtpError(ConnectionTimeoutError);
+ return false;
+ }
+
+ // Send ELHO one more time
+ sendMessage("EHLO " + name);
+
+ // Wait for the server's response
+ waitForResponse();
+
+ // The response code needs to be 250.
+ if (responseCode != 250) {
+ emit smtpError(ServerError);
+ return false;
+ }
+ }
+ } catch (ResponseTimeoutException) {
+ return false;
+ } catch (SendMessageTimeoutException) {
+ return false;
+ }
+
+ // If no errors occured the function returns true.
+ return true;
+}
+
+bool SmtpClient::login() { return login(user, password, authMethod); }
+
+bool SmtpClient::login(const QString &user, const QString &password,
+ AuthMethod method) {
+ try {
+ if (method == AuthPlain) {
+ // Sending command: AUTH PLAIN base64('\0' + username + '\0' + password)
+ sendMessage("AUTH PLAIN " + QByteArray()
+ .append((char) 0)
+ .append(user.toUtf8())
+ .append((char) 0)
+ .append(password.toUtf8())
+ .toBase64());
+
+ // Wait for the server's response
+ waitForResponse();
+
+ // If the response is not 235 then the authentication was faild
+ if (responseCode != 235) {
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+ } else if (method == AuthLogin) {
+ // Sending command: AUTH LOGIN
+ sendMessage("AUTH LOGIN");
+
+ // Wait for 334 response code
+ waitForResponse();
+ if (responseCode != 334) {
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+
+ // Send the username in base64
+ sendMessage(QByteArray().append(user.toUtf8()).toBase64());
+
+ // Wait for 334
+ waitForResponse();
+ if (responseCode != 334) {
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+
+ // Send the password in base64
+ sendMessage(QByteArray().append(password.toUtf8()).toBase64());
+
+ // Wait for the server's responce
+ waitForResponse();
+
+ // If the response is not 235 then the authentication was faild
+ if (responseCode != 235) {
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+ }
+ } catch (ResponseTimeoutException) {
+ // Responce Timeout exceeded
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ } catch (SendMessageTimeoutException) {
+ // Send Timeout exceeded
+ emit smtpError(AuthenticationFailedError);
+ return false;
+ }
+
+ return true;
+}
+
+bool SmtpClient::sendMail(MimeMessage &email) {
+ try {
+ // Send the MAIL command with the sender
+ sendMessage("MAIL FROM:<" + email.getSender().getAddress() + ">");
+
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+
+ // Send RCPT command for each recipient
+ QList<EmailAddress *>::const_iterator it, itEnd;
+ // To (primary recipients)
+ for (it = email.getRecipients().begin(),
+ itEnd = email.getRecipients().end();
+ it != itEnd; ++it) {
+
+ sendMessage("RCPT TO:<" + (*it)->getAddress() + ">");
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+ }
+
+ // Cc (carbon copy)
+ for (it = email.getRecipients(MimeMessage::Cc).begin(),
+ itEnd = email.getRecipients(MimeMessage::Cc).end();
+ it != itEnd; ++it) {
+ sendMessage("RCPT TO:<" + (*it)->getAddress() + ">");
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+ }
+
+ // Bcc (blind carbon copy)
+ for (it = email.getRecipients(MimeMessage::Bcc).begin(),
+ itEnd = email.getRecipients(MimeMessage::Bcc).end();
+ it != itEnd; ++it) {
+ sendMessage("RCPT TO:<" + (*it)->getAddress() + ">");
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+ }
+
+ // Send DATA command
+ sendMessage("DATA");
+ waitForResponse();
+
+ if (responseCode != 354)
+ return false;
+
+ sendMessage(email.toString());
+
+ // Send \r\n.\r\n to end the mail data
+ sendMessage(".");
+
+ waitForResponse();
+
+ if (responseCode != 250)
+ return false;
+ } catch (ResponseTimeoutException) {
+ return false;
+ } catch (SendMessageTimeoutException) {
+ return false;
+ }
+
+ return true;
+}
+
+void SmtpClient::quit() {
+ try {
+ sendMessage("QUIT");
+ } catch (SmtpClient::SendMessageTimeoutException) {
+ // Manually close the connection to the smtp server if message "QUIT" wasn't
+ // received by the smtp server
+ if (socket->state() == QAbstractSocket::ConnectedState ||
+ socket->state() == QAbstractSocket::ConnectingState ||
+ socket->state() == QAbstractSocket::HostLookupState)
+ socket->disconnectFromHost();
+ }
+}
+
+/* [3] --- */
+
+/* [4] Protected methods */
+
+void SmtpClient::waitForResponse() {
+ do {
+ if (!socket->waitForReadyRead(responseTimeout)) {
+ emit smtpError(ResponseTimeoutError);
+ throw ResponseTimeoutException();
+ }
+
+ while (socket->canReadLine()) {
+ // Save the server's response
+ responseText = socket->readLine();
+
+ // Extract the respose code from the server's responce (first 3 digits)
+ responseCode = responseText.leftRef(3).toInt();
+
+ if (responseCode / 100 == 4)
+ emit smtpError(ServerError);
+
+ if (responseCode / 100 == 5)
+ emit smtpError(ClientError);
+
+ if (responseText[3] == ' ') {
+ return;
+ }
+ }
+ } while (true);
+}
+
+void SmtpClient::sendMessage(const QString &text) {
+ socket->write(text.toUtf8() + "\r\n");
+ if (!socket->waitForBytesWritten(sendMessageTimeout)) {
+ emit smtpError(SendDataTimeoutError);
+ throw SendMessageTimeoutException();
+ }
+}
+
+/* [4] --- */
+
+/* [5] Slots for the socket's signals */
+
+void SmtpClient::socketStateChanged(QAbstractSocket::SocketState /*state*/) {}
+
+void SmtpClient::socketError(QAbstractSocket::SocketError /*socketError*/) {}
+
+void SmtpClient::socketReadyRead() {}
+
+/* [5] --- */
diff --git a/src/ui/AboutDialog.cpp b/src/ui/AboutDialog.cpp
deleted file mode 100644
index e51f225d..00000000
--- a/src/ui/AboutDialog.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-#include "ui/AboutDialog.h"
-
-AboutDialog::AboutDialog(QWidget *parent)
- : QDialog(parent) {
- this->setWindowTitle(tr("About ") + qApp->applicationName());
-
- auto *tabWidget = new QTabWidget;
- auto *infoTab = new InfoTab;
- auto *translatorsTab = new TranslatorsTab;
-
- tabWidget->addTab(infoTab, tr("General"));
- tabWidget->addTab(translatorsTab, tr("Translators"));
-
- auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
- connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(tabWidget);
- mainLayout->addWidget(buttonBox);
- setLayout(mainLayout);
-
- this->exec();
-}
-
-InfoTab::InfoTab(QWidget *parent)
- : QWidget(parent) {
- auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
- auto *text = new QString("<center><h2>" + qApp->applicationName() + "</h2></center>"
- + "<center><b>" + qApp->applicationVersion() + "</b></center>"
- + "<center>" + GIT_VERSION + "</center>"
- + tr("<br><center>GPGFrontend is an easy-to-use, compact, <br>"
- "cross-platform, and installation-free gpg front-end tool.<br>"
- "It visualizes most of the common operations of gpg commands.<br>"
- "It's licensed under the GPL v3<br><br>"
- "<b>Developer:</b><br>"
- "Saturneric<br><br>"
- "If you have any questions or suggestions, raise an issue<br/>"
- "at <a href=\"https://github.com/saturneric/GpgFrontend\">GitHub</a> or send a mail to my mailing list at <a href=\"mailto:[email protected]\">[email protected]</a>.") +
- tr("<br><br> Built with Qt ") + qVersion()
- + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() +
- tr("<br>Built at ") + BUILD_TIMESTAMP + "</center>");
-
- auto *layout = new QGridLayout();
- auto *pixmapLabel = new QLabel();
- pixmapLabel->setPixmap(*pixmap);
- layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
- auto *aboutLabel = new QLabel();
- aboutLabel->setText(*text);
- aboutLabel->setOpenExternalLinks(true);
- layout->addWidget(aboutLabel, 1, 0, 1, -1);
- layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
- QSizePolicy::Fixed), 2, 1, 1, 1);
-
- setLayout(layout);
-}
-
-TranslatorsTab::TranslatorsTab(QWidget *parent)
- : QWidget(parent) {
- QFile translatorsFile;
- translatorsFile.setFileName(qApp->applicationDirPath() + "/About");
- translatorsFile.open(QIODevice::ReadOnly);
- QByteArray inBuffer = translatorsFile.readAll();
-
- auto *label = new QLabel(inBuffer);
- auto *mainLayout = new QVBoxLayout(this);
- mainLayout->addWidget(label);
-
- setLayout(mainLayout);
-}
-
diff --git a/src/ui/AttachmentTableModel.cpp b/src/ui/AttachmentTableModel.cpp
deleted file mode 100644
index 79cbdf9b..00000000
--- a/src/ui/AttachmentTableModel.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-#include "ui/AttachmentTableModel.h"
-
-#include <utility>
-
-/** compare with http://doc.qt.nokia.com/4.6/itemviews-addressbook.html
- */
-
-AttachmentTableModel::AttachmentTableModel(QObject *parent) :
- QAbstractTableModel(parent) {
-}
-
-AttachmentTableModel::AttachmentTableModel(QList<MimePart> mimeparts, QObject *parent) :
- QAbstractTableModel(parent) {
- listOfMimeparts = std::move(mimeparts);
-}
-
-
-void AttachmentTableModel::add(const MimePart &mp) {
- listOfMimeparts.append(mp);
- //QModelIndex changedIndex0 = createIndex(listOfMimeparts.size(), 0);
- //QModelIndex changedIndex1 = createIndex(listOfMimeparts.size(), 1);
-
- //emit(dataChanged(changedIndex0, changedIndex1));
- // TODO: check the data-changed signal
- // reset();
-}
-
-MimePart AttachmentTableModel::getSelectedMimePart(QModelIndex index) {
- return listOfMimeparts.at(index.row());
-}
-
-MimePart AttachmentTableModel::getMimePart(int index) {
- return listOfMimeparts.at(index);
-}
-
-/*QList<MimePart> AttachmentTableModel::getSelectedMimeParts(QModelIndexList indexes){
-
- foreach(QModelIndex index, indexes) {
- qDebug() << "ir: "<< index.row();
- }
-
-}*/
-
-int AttachmentTableModel::rowCount(const QModelIndex &parent) const {
- Q_UNUSED(parent);
- return listOfMimeparts.size();
-}
-
-int AttachmentTableModel::columnCount(const QModelIndex &parent) const {
- Q_UNUSED(parent);
- return 2;
-}
-
-QVariant AttachmentTableModel::data(const QModelIndex &index, int role) const {
-
- //qDebug() << "called, index: " << index.column();
-
- if (!index.isValid())
- return QVariant();
-
- if (index.row() >= listOfMimeparts.size() || index.row() < 0)
- return QVariant();
-
- if (role == Qt::DisplayRole) {
- MimePart mp = listOfMimeparts.at(index.row());
-
- if (index.column() == 0)
- return mp.header.getParam("Content-Type", "name");
- if (index.column() == 1)
- return mp.header.getValue("Content-Type");
-
- }
-
- // set icon
- // TODO more generic matching, e.g. for audio
- if (role == Qt::DecorationRole && index.column() == 0) {
- MimePart mp = listOfMimeparts.at(index.row());
- QString icon;
- if (mp.header.getValue("Content-Type").startsWith("image")) {
- icon = ":mimetypes/image-x-generic.png";
- } else {
- icon = mp.header.getValue("Content-Type").replace("/", "-");
- icon = ":mimetypes/" + icon + ".png";
- }
- if (!QFile::exists(icon)) icon = ":mimetypes/unknown.png";
- return QIcon(icon);
- }
-
- return QVariant();
-}
-
-QVariant AttachmentTableModel::headerData(int section, Qt::Orientation orientation, int role) const {
- //qDebug() << "called, section: " << section;
- if (role != Qt::DisplayRole)
- return QVariant();
-
- if (orientation == Qt::Horizontal) {
- switch (section) {
- case 0:
- return tr("Filename");
-
- case 1:
- return tr("Contenttype");
-
- default:
- return QVariant();
- }
- }
- return QVariant();
-}
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 68f57b81..618b5d28 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -3,6 +3,7 @@ aux_source_directory(./keypair_details UI_SOURCE)
aux_source_directory(./widgets UI_SOURCE)
aux_source_directory(./keygen UI_SOURCE)
aux_source_directory(./main_window UI_SOURCE)
+aux_source_directory(./help UI_SOURCE)
add_library(gpgfrontend-ui STATIC ${UI_SOURCE})
diff --git a/src/ui/FileEncryptionDialog.cpp b/src/ui/FileEncryptionDialog.cpp
index 9cb7b00a..e92dfc90 100755
--- a/src/ui/FileEncryptionDialog.cpp
+++ b/src/ui/FileEncryptionDialog.cpp
@@ -203,27 +203,50 @@ void FileEncryptionDialog::slotExecuteAction() {
QVector<GpgKey> keys;
mKeyList->getCheckedKeys(keys);
+ qDebug() << "slotExecuteAction" << mAction;
+
if (mAction == Encrypt) {
- if (!mCtx->encrypt(keys, inBuffer, outBuffer, nullptr)) return;
+ qDebug() << "Action Encrypt";
+ gpgme_error_t err = mCtx->encrypt(keys, inBuffer, outBuffer, nullptr);
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
+ qDebug() << "Error" << gpgme_strerror(err);
+ QMessageBox::warning(this, tr("Error"),
+ tr("Error Occurred During Encryption"));
+ return;
+ }
}
if (mAction == Decrypt) {
- if (!mCtx->decrypt(inBuffer, outBuffer, nullptr)) return;
+ qDebug() << "Action Decrypt";
+ gpgme_error_t err = mCtx->decrypt(inBuffer, outBuffer, nullptr);
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
+ qDebug() << "Error" << gpgme_strerror(err);
+ QMessageBox::warning(this, tr("Error"),
+ tr("Error Occurred During Decryption"));
+ return;
+ }
}
if (mAction == Sign) {
- if (gpgme_err_code(mCtx->sign(keys, inBuffer, outBuffer, true)) != GPG_ERR_NO_ERROR) return;
+ qDebug() << "Action Sign";
+ gpgme_error_t err = mCtx->sign(keys, inBuffer, outBuffer, true);
+ if (gpgme_err_code(err) != GPG_ERR_NO_ERROR) {
+ qDebug() << "Error" << gpgme_strerror(err);
+ QMessageBox::warning(this, tr("Error"),
+ tr("Error Occurred During Signature"));
+ return;
+ }
}
if (mAction == Verify) {
- QFile signfile;
- signfile.setFileName(signFileEdit->text());
- if (!signfile.open(QIODevice::ReadOnly)) {
+ QFile sign_file;
+ sign_file.setFileName(signFileEdit->text());
+ if (!sign_file.open(QIODevice::ReadOnly)) {
statusLabel->setText(tr("Couldn't open file"));
signFileEdit->setStyleSheet("QLineEdit { background: yellow }");
return;
}
- auto signBuffer = signfile.readAll();
+ auto signBuffer = sign_file.readAll();
gpgme_verify_result_t result;
auto error = mCtx->verify(&inBuffer, &signBuffer, &result);
new VerifyDetailsDialog(this, mCtx, mKeyList, error, result);
diff --git a/src/ui/KeyMgmt.cpp b/src/ui/KeyMgmt.cpp
index 0e2d9c9a..ce5343bf 100755
--- a/src/ui/KeyMgmt.cpp
+++ b/src/ui/KeyMgmt.cpp
@@ -78,7 +78,7 @@ KeyMgmt::KeyMgmt(GpgME::GpgContext *ctx, QWidget *parent ) :
this->settings.setValue("keymgmt/setWindowSize", true);
}
- setWindowTitle(tr("KeyPairs Management"));
+ setWindowTitle(tr("Key Pair Management"));
mKeyList->addMenuAction(deleteSelectedKeysAct);
mKeyList->addMenuAction(showKeyDetailsAct);
}
diff --git a/src/ui/KeyServerImportDialog.cpp b/src/ui/KeyServerImportDialog.cpp
index ec740691..a1355120 100644
--- a/src/ui/KeyServerImportDialog.cpp
+++ b/src/ui/KeyServerImportDialog.cpp
@@ -176,7 +176,7 @@ void KeyServerImportDialog::setMessage(const QString &text, bool error) {
void KeyServerImportDialog::slotSearch() {
if (searchLineEdit->text().isEmpty()) {
- setMessage(tr("<h4>Text is empty.</h4>"), false);
+ setMessage("<h4>" + tr("Text is empty.") + "</h4>", false);
return;
}
@@ -227,23 +227,23 @@ void KeyServerImportDialog::slotSearchFinished() {
if (firstLine.contains("Error")) {
QString text = QString(reply->readLine(1024));
if (text.contains("Too many responses")) {
- setMessage(tr("<h4>CToo many responses from keyserver!</h4>"), true);
+ setMessage("<h4>" +tr("Too many responses from keyserver!") + "</h4>", true);
return;
} else if (text.contains("No keys found")) {
// if string looks like hex string, search again with 0x prepended
QRegExp rx("[0-9A-Fa-f]*");
QString query = searchLineEdit->text();
if (rx.exactMatch(query)) {
- setMessage(tr("<h4>No keys found, input may be kexId, retrying search with 0x.</h4>"), true);
+ setMessage("<h4>" + tr("No keys found, input may be kexId, retrying search with 0x.") + "</h4>", true);
searchLineEdit->setText(query.prepend("0x"));
this->slotSearch();
return;
} else {
- setMessage(tr("<h4>No keys found containing the search string!</h4>"), true);
+ setMessage("<h4>" +tr("No keys found containing the search string!") + "</h4>", true);
return;
}
} else if (text.contains("Insufficiently specific words")) {
- setMessage(tr("<h4>Insufficiently specific search string!</h4>"), true);
+ setMessage("<h4>" + tr("Insufficiently specific search string!") + "</h4>", true);
return;
} else {
setMessage(text, true);
diff --git a/src/ui/KeyUploadDialog.cpp b/src/ui/KeyUploadDialog.cpp
index e28b4230..faf892f0 100644
--- a/src/ui/KeyUploadDialog.cpp
+++ b/src/ui/KeyUploadDialog.cpp
@@ -36,9 +36,13 @@ KeyUploadDialog::KeyUploadDialog(GpgME::GpgContext *ctx, const QVector<GpgKey> &
auto *pb = new QProgressBar();
pb->setRange(0, 0);
+ pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ pb->setTextVisible(false);
auto *layout = new QVBoxLayout();
layout->addWidget(pb);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
this->setLayout(layout);
this->setModal(true);
diff --git a/src/ui/SendMailDialog.cpp b/src/ui/SendMailDialog.cpp
new file mode 100644
index 00000000..5bea7cb2
--- /dev/null
+++ b/src/ui/SendMailDialog.cpp
@@ -0,0 +1,173 @@
+/**
+ * This file is part of GPGFrontend.
+ *
+ * GPGFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#include "ui/SendMailDialog.h"
+
+#include <utility>
+#include "smtp/SmtpMime"
+
+SendMailDialog::SendMailDialog(QString text, QWidget *parent)
+ : QDialog(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", QSettings::IniFormat), mText(std::move(text)) {
+
+ if (smtpAddress.isEmpty()) {
+ QMessageBox::critical(this, tr("Incomplete configuration"),
+ tr("The SMTP address is empty, please go to the setting interface to complete the configuration."));
+
+ deleteLater();
+ return;
+
+ }
+
+ senderEdit = new QLineEdit();
+ senderEdit->setText(defaultSender);
+ recipientEdit = new QTextEdit();
+ recipientEdit->setPlaceholderText("One or more email addresses. Please use ; to separate.");
+ subjectEdit = new QLineEdit();
+
+ errorLabel = new QLabel();
+
+ qDebug() << "Send Mail Settings" << smtpAddress << username << password << defaultSender << connectionTypeSettings;
+
+ confirmButton = new QPushButton("Confirm");
+
+ auto layout = new QGridLayout();
+ layout->addWidget(new QLabel("Sender"), 0, 0);
+ layout->addWidget(senderEdit, 0, 1);
+ layout->addWidget(new QLabel("Recipient"), 1, 0);
+ layout->addWidget(recipientEdit, 1, 1);
+ layout->addWidget(new QLabel("Subject"), 2, 0);
+ layout->addWidget(subjectEdit, 2, 1);
+ layout->addWidget(confirmButton, 3, 1);
+ layout->addWidget(errorLabel, 4, 0, 1, 2);
+
+ connect(confirmButton, SIGNAL(clicked(bool)), this, SLOT(slotConfirm()));
+
+ this->setLayout(layout);
+ this->setWindowTitle("Send Mail");
+ this->setModal(true);
+ this->setFixedWidth(320);
+ this->show();
+}
+
+bool SendMailDialog::check_email_address(const QString &str) {
+ return re_email.match(str).hasMatch();
+}
+
+void SendMailDialog::slotConfirm() {
+
+ QString errString;
+ errorLabel->clear();
+
+ QStringList rcptStringList = recipientEdit->toPlainText().split(';');
+
+ if (rcptStringList.isEmpty()) {
+ errString.append(tr(" Recipient cannot be empty \n"));
+ } else {
+ for (const auto& reci : rcptStringList) {
+ qDebug() << "Receiver" << reci.trimmed();
+ if (!check_email_address(reci.trimmed())) {
+ errString.append(tr(" One or more Recipient's Email Address is invalid \n"));
+ break;
+ }
+ }
+ }
+ if (senderEdit->text().isEmpty()) {
+ errString.append(tr(" Sender cannot be empty \n"));
+ } else if (!check_email_address(senderEdit->text())) {
+ errString.append(tr(" Sender's Email Address is invalid \n"));
+ }
+
+ if (!errString.isEmpty()) {
+ errorLabel->setAutoFillBackground(true);
+ QPalette error = errorLabel->palette();
+ error.setColor(QPalette::Window, "#ff8080");
+ errorLabel->setPalette(error);
+ errorLabel->setText(errString);
+ return;
+ }
+
+ SmtpClient::ConnectionType connectionType = SmtpClient::ConnectionType::TcpConnection;
+
+ if (connectionTypeSettings == "SSL") {
+ connectionType = SmtpClient::ConnectionType::SslConnection;
+ } else if (connectionTypeSettings == "TLS") {
+ connectionType = SmtpClient::ConnectionType::TlsConnection;
+ } else if (connectionTypeSettings == "STARTTLS") {
+ connectionType = SmtpClient::ConnectionType::TlsConnection;
+ } else {
+ connectionType = SmtpClient::ConnectionType::TcpConnection;
+ }
+
+ SmtpClient smtp(smtpAddress, port, connectionType);
+
+ // We need to set the username (your email address) and the password
+ // for smtp authentification.
+
+ smtp.setUser(username);
+ smtp.setPassword(password);
+
+ // Now we create a MimeMessage object. This will be the email.
+
+ MimeMessage message;
+
+ message.setSender(new EmailAddress(senderEdit->text()));
+ for (const auto &reci : rcptStringList) {
+ if(!reci.isEmpty())
+ message.addRecipient(new EmailAddress(reci.trimmed()));
+ }
+ message.setSubject(subjectEdit->text());
+
+ // Now add some text to the email.
+ // First we create a MimeText object.
+
+ MimeText text;
+
+ text.setText(mText);
+
+ // Now add it to the mail
+ message.addPart(&text);
+
+ // Now we can send the mail
+ if (!smtp.connectToHost()) {
+ qDebug() << "Connect to SMTP Server Failed";
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Connect SMTP Server"));
+ return;
+ }
+ if (!smtp.login()) {
+ qDebug() << "Login to SMTP Server Failed";
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Login into SMTP Server"));
+ return;
+ }
+ if (!smtp.sendMail(message)) {
+ qDebug() << "Send Mail to SMTP Server Failed";
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Send Mail to SMTP Server"));
+ return;
+ }
+ smtp.quit();
+
+ // Close after sending email
+ QMessageBox::information(this, tr("Success"), tr("Succeed in Sending Mail to SMTP Server"));
+ deleteLater();
+}
diff --git a/src/ui/SettingsDialog.cpp b/src/ui/SettingsDialog.cpp
index 74c507e4..1732d718 100755
--- a/src/ui/SettingsDialog.cpp
+++ b/src/ui/SettingsDialog.cpp
@@ -23,203 +23,205 @@
*/
#include "ui/SettingsDialog.h"
+#include "smtp/SmtpMime"
+#include "ui/WaitingDialog.h"
SettingsDialog::SettingsDialog(GpgME::GpgContext *ctx, QWidget *parent)
- : QDialog(parent) {
- mCtx = ctx;
- tabWidget = new QTabWidget;
- generalTab = new GeneralTab(mCtx);
- appearanceTab = new AppearanceTab;
- mimeTab = new MimeTab;
- keyserverTab = new KeyserverTab;
- advancedTab = new AdvancedTab;
- gpgPathsTab = new GpgPathsTab;
-
- tabWidget->addTab(generalTab, tr("General"));
- tabWidget->addTab(appearanceTab, tr("Appearance"));
- tabWidget->addTab(mimeTab, tr("PGP/Mime"));
- tabWidget->addTab(keyserverTab, tr("Key Server"));
- // tabWidget->addTab(gpgPathsTab, tr("Gpg paths"));
- tabWidget->addTab(advancedTab, tr("Advanced"));
-
- buttonBox =
- new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
-
- connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAccept()));
- connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(tabWidget);
- mainLayout->addWidget(buttonBox);
- setLayout(mainLayout);
-
- setWindowTitle(tr("Settings"));
-
- // slots for handling the restartneeded member
- this->slotSetRestartNeeded(false);
- connect(generalTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
- connect(appearanceTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
- connect(mimeTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
- connect(keyserverTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
- connect(advancedTab, SIGNAL(signalRestartNeeded(bool)), this,
- SLOT(slotSetRestartNeeded(bool)));
-
- connect(this, SIGNAL(signalRestartNeeded(bool)), parent,
- SLOT(slotSetRestartNeeded(bool)));
-
- this->show();
+ : QDialog(parent) {
+ mCtx = ctx;
+ tabWidget = new QTabWidget;
+ generalTab = new GeneralTab(mCtx);
+ appearanceTab = new AppearanceTab;
+ sendMailTab = new SendMailTab;
+ keyserverTab = new KeyserverTab;
+ advancedTab = new AdvancedTab;
+ gpgPathsTab = new GpgPathsTab;
+
+ tabWidget->addTab(generalTab, tr("General"));
+ tabWidget->addTab(appearanceTab, tr("Appearance"));
+ tabWidget->addTab(sendMailTab, tr("Send Mail"));
+ tabWidget->addTab(keyserverTab, tr("Key Server"));
+ // tabWidget->addTab(gpgPathsTab, tr("Gpg paths"));
+ tabWidget->addTab(advancedTab, tr("Advanced"));
+
+ buttonBox =
+ new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAccept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(tabWidget);
+ mainLayout->addWidget(buttonBox);
+ setLayout(mainLayout);
+
+ setWindowTitle(tr("Settings"));
+
+ // slots for handling the restartneeded member
+ this->slotSetRestartNeeded(false);
+ connect(generalTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+ connect(appearanceTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+ connect(sendMailTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+ connect(keyserverTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+ connect(advancedTab, SIGNAL(signalRestartNeeded(bool)), this,
+ SLOT(slotSetRestartNeeded(bool)));
+
+ connect(this, SIGNAL(signalRestartNeeded(bool)), parent,
+ SLOT(slotSetRestartNeeded(bool)));
+
+ this->show();
}
bool SettingsDialog::getRestartNeeded() const { return this->restartNeeded; }
void SettingsDialog::slotSetRestartNeeded(bool needed) {
- this->restartNeeded = needed;
+ this->restartNeeded = needed;
}
void SettingsDialog::slotAccept() {
- generalTab->applySettings();
- mimeTab->applySettings();
- appearanceTab->applySettings();
- keyserverTab->applySettings();
- advancedTab->applySettings();
- gpgPathsTab->applySettings();
- if (getRestartNeeded()) {
- emit signalRestartNeeded(true);
- }
- close();
+ generalTab->applySettings();
+ sendMailTab->applySettings();
+ appearanceTab->applySettings();
+ keyserverTab->applySettings();
+ advancedTab->applySettings();
+ gpgPathsTab->applySettings();
+ if (getRestartNeeded()) {
+ emit signalRestartNeeded(true);
+ }
+ close();
}
// http://www.informit.com/articles/article.aspx?p=1405555&seqNum=3
// http://developer.qt.nokia.com/wiki/How_to_create_a_multi_language_application
QHash<QString, QString> SettingsDialog::listLanguages() {
- QHash<QString, QString> languages;
+ QHash<QString, QString> languages;
- languages.insert("", tr("System Default"));
+ languages.insert("", tr("System Default"));
- QString appPath = qApp->applicationDirPath();
- QDir qmDir = QDir(RESOURCE_DIR(appPath) + "/ts/");
- QStringList fileNames = qmDir.entryList(QStringList("gpgfrontend_*.qm"));
+ QString appPath = qApp->applicationDirPath();
+ QDir qmDir = QDir(RESOURCE_DIR(appPath) + "/ts/");
+ QStringList fileNames = qmDir.entryList(QStringList("gpgfrontend_*.qm"));
- for (int i = 0; i < fileNames.size(); ++i) {
- QString locale = fileNames[i];
- locale.truncate(locale.lastIndexOf('.'));
- locale.remove(0, locale.indexOf('_') + 1);
+ for (int i = 0; i < fileNames.size(); ++i) {
+ QString locale = fileNames[i];
+ locale.truncate(locale.lastIndexOf('.'));
+ locale.remove(0, locale.indexOf('_') + 1);
- // this works in qt 4.8
- QLocale qloc(locale);
+ // this works in qt 4.8
+ QLocale qloc(locale);
#if QT_VERSION < 0x040800
- QString language =
- QLocale::languageToString(qloc.language()) + " (" + locale +
- ")"; //+ " (" + QLocale::languageToString(qloc.language()) + ")";
+ QString language =
+ QLocale::languageToString(qloc.language()) + " (" + locale +
+ ")"; //+ " (" + QLocale::languageToString(qloc.language()) + ")";
#else
- QString language = qloc.nativeLanguageName() + " (" + locale + ")";
+ QString language = qloc.nativeLanguageName() + " (" + locale + ")";
#endif
- languages.insert(locale, language);
- }
- return languages;
+ languages.insert(locale, language);
+ }
+ return languages;
}
GeneralTab::GeneralTab(GpgME::GpgContext *ctx, QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- mCtx = ctx;
-
- /*****************************************
- * remember Password-Box
- *****************************************/
- auto *rememberPasswordBox = new QGroupBox(tr("Remember Password"));
- auto *rememberPasswordBoxLayout = new QHBoxLayout();
- rememberPasswordCheckBox =
- new QCheckBox(tr("Remember password until closing gpg4usb"), this);
- rememberPasswordBoxLayout->addWidget(rememberPasswordCheckBox);
- rememberPasswordBox->setLayout(rememberPasswordBoxLayout);
-
- /*****************************************
- * Save-Checked-Keys-Box
- *****************************************/
- auto *saveCheckedKeysBox = new QGroupBox(tr("Save Checked Keys"));
- auto *saveCheckedKeysBoxLayout = new QHBoxLayout();
- saveCheckedKeysCheckBox = new QCheckBox(
- tr("Save checked private keys on exit and restore them on next start."),
- this);
- saveCheckedKeysBoxLayout->addWidget(saveCheckedKeysCheckBox);
- saveCheckedKeysBox->setLayout(saveCheckedKeysBoxLayout);
-
- /*****************************************
- * Key-Impport-Confirmation Box
- *****************************************/
- auto *importConfirmationBox =
- new QGroupBox(tr("Confirm drag'n'drop key import"));
- auto *importConfirmationBoxLayout = new QHBoxLayout();
- importConfirmationCheckBox = new QCheckBox(
- tr("Import files dropped on the keylist without confirmation."), this);
- importConfirmationBoxLayout->addWidget(importConfirmationCheckBox);
- importConfirmationBox->setLayout(importConfirmationBoxLayout);
-
- /*****************************************
- * Language Select Box
- *****************************************/
- auto *langBox = new QGroupBox(tr("Language"));
- auto *langBoxLayout = new QVBoxLayout();
- langSelectBox = new QComboBox;
- lang = SettingsDialog::listLanguages();
-
- foreach (QString l, lang) { langSelectBox->addItem(l); }
-
- langBoxLayout->addWidget(langSelectBox);
- langBoxLayout->addWidget(
- new QLabel(tr("<b>NOTE: </b> GpgFrontend will restart automatically if "
- "you change the language!")));
- langBox->setLayout(langBoxLayout);
- connect(langSelectBox, SIGNAL(currentIndexChanged(int)), this,
- SLOT(slotLanguageChanged()));
-
- /*****************************************
- * Own Key Select Box
- *****************************************/
- auto *ownKeyBox = new QGroupBox(tr("Own key"));
- auto *ownKeyBoxLayout = new QVBoxLayout();
- ownKeySelectBox = new QComboBox;
-
- ownKeyBox->setLayout(ownKeyBoxLayout);
- mKeyList = new KeyList(mCtx);
-
- // Fill the keyid hashmap
- keyIds.insert("", tr("<none>"));
-
- for (const auto &keyid : *mKeyList->getAllPrivateKeys()) {
- auto &key = mCtx->getKeyById(keyid);
- keyIds.insert(key.id, key.uids.first().uid);
- }
- for (const auto &k : keyIds.keys()) {
- ownKeySelectBox->addItem(keyIds.find(k).value());
- keyIdsList.append(k);
- }
- connect(ownKeySelectBox, SIGNAL(currentIndexChanged(int)), this,
- SLOT(slotOwnKeyIdChanged()));
-
- ownKeyBoxLayout->addWidget(new QLabel(
- tr("Key pair for synchronization and identity authentication")));
- ownKeyBoxLayout->addWidget(ownKeySelectBox);
-
- /*****************************************
- * Mainlayout
- *****************************************/
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(rememberPasswordBox);
- mainLayout->addWidget(saveCheckedKeysBox);
- mainLayout->addWidget(importConfirmationBox);
- mainLayout->addWidget(langBox);
- mainLayout->addWidget(ownKeyBox);
-
- setSettings();
- mainLayout->addStretch(1);
- setLayout(mainLayout);
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+ mCtx = ctx;
+
+ /*****************************************
+ * remember Password-Box
+ *****************************************/
+ auto *rememberPasswordBox = new QGroupBox(tr("Remember Password"));
+ auto *rememberPasswordBoxLayout = new QHBoxLayout();
+ rememberPasswordCheckBox =
+ new QCheckBox(tr("Remember password until closing gpg4usb"), this);
+ rememberPasswordBoxLayout->addWidget(rememberPasswordCheckBox);
+ rememberPasswordBox->setLayout(rememberPasswordBoxLayout);
+
+ /*****************************************
+ * Save-Checked-Keys-Box
+ *****************************************/
+ auto *saveCheckedKeysBox = new QGroupBox(tr("Save Checked Keys"));
+ auto *saveCheckedKeysBoxLayout = new QHBoxLayout();
+ saveCheckedKeysCheckBox = new QCheckBox(
+ tr("Save checked private keys on exit and restore them on next start."),
+ this);
+ saveCheckedKeysBoxLayout->addWidget(saveCheckedKeysCheckBox);
+ saveCheckedKeysBox->setLayout(saveCheckedKeysBoxLayout);
+
+ /*****************************************
+ * Key-Impport-Confirmation Box
+ *****************************************/
+ auto *importConfirmationBox =
+ new QGroupBox(tr("Confirm drag'n'drop key import"));
+ auto *importConfirmationBoxLayout = new QHBoxLayout();
+ importConfirmationCheckBox = new QCheckBox(
+ tr("Import files dropped on the keylist without confirmation."), this);
+ importConfirmationBoxLayout->addWidget(importConfirmationCheckBox);
+ importConfirmationBox->setLayout(importConfirmationBoxLayout);
+
+ /*****************************************
+ * Language Select Box
+ *****************************************/
+ auto *langBox = new QGroupBox(tr("Language"));
+ auto *langBoxLayout = new QVBoxLayout();
+ langSelectBox = new QComboBox;
+ lang = SettingsDialog::listLanguages();
+
+ foreach (QString l, lang) { langSelectBox->addItem(l); }
+
+ langBoxLayout->addWidget(langSelectBox);
+ langBoxLayout->addWidget(
+ new QLabel(tr("<b>NOTE: </b> GpgFrontend will restart automatically if "
+ "you change the language!")));
+ langBox->setLayout(langBoxLayout);
+ connect(langSelectBox, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(slotLanguageChanged()));
+
+ /*****************************************
+ * Own Key Select Box
+ *****************************************/
+ auto *ownKeyBox = new QGroupBox(tr("Own key"));
+ auto *ownKeyBoxLayout = new QVBoxLayout();
+ ownKeySelectBox = new QComboBox;
+
+ ownKeyBox->setLayout(ownKeyBoxLayout);
+ mKeyList = new KeyList(mCtx);
+
+ // Fill the keyid hashmap
+ keyIds.insert("", tr("<none>"));
+
+ for (const auto &keyid : *mKeyList->getAllPrivateKeys()) {
+ auto &key = mCtx->getKeyById(keyid);
+ keyIds.insert(key.id, key.uids.first().uid);
+ }
+ for (const auto &k : keyIds.keys()) {
+ ownKeySelectBox->addItem(keyIds.find(k).value());
+ keyIdsList.append(k);
+ }
+ connect(ownKeySelectBox, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(slotOwnKeyIdChanged()));
+
+ ownKeyBoxLayout->addWidget(new QLabel(
+ tr("Key pair for synchronization and identity authentication")));
+ ownKeyBoxLayout->addWidget(ownKeySelectBox);
+
+ /*****************************************
+ * Mainlayout
+ *****************************************/
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(rememberPasswordBox);
+ mainLayout->addWidget(saveCheckedKeysBox);
+ mainLayout->addWidget(importConfirmationBox);
+ mainLayout->addWidget(langBox);
+ mainLayout->addWidget(ownKeyBox);
+
+ setSettings();
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
}
/**********************************
@@ -228,32 +230,32 @@ GeneralTab::GeneralTab(GpgME::GpgContext *ctx, QWidget *parent)
* appropriately
**********************************/
void GeneralTab::setSettings() {
- // Keysaving
- if (settings.value("keys/saveKeyChecked").toBool()) {
- saveCheckedKeysCheckBox->setCheckState(Qt::Checked);
- }
-
- // Language setting
- QString langKey = settings.value("int/lang").toString();
- QString langValue = lang.value(langKey);
- if (langKey != "") {
- langSelectBox->setCurrentIndex(langSelectBox->findText(langValue));
- }
-
- QString ownKeyId = settings.value("general/ownKeyId").toString();
- qDebug() << "OwnKeyId" << ownKeyId;
- if (ownKeyId.isEmpty()) {
- ownKeySelectBox->setCurrentText("<none>");
- } else {
- const auto text = keyIds.find(ownKeyId).value();
- qDebug() << "OwnKey" << ownKeyId << text;
- ownKeySelectBox->setCurrentText(text);
- }
-
- // Get own key information from keydb/gpg.conf (if contained)
- if (settings.value("general/confirmImportKeys", Qt::Checked).toBool()) {
- importConfirmationCheckBox->setCheckState(Qt::Checked);
- }
+ // Keysaving
+ if (settings.value("keys/saveKeyChecked").toBool()) {
+ saveCheckedKeysCheckBox->setCheckState(Qt::Checked);
+ }
+
+ // Language setting
+ QString langKey = settings.value("int/lang").toString();
+ QString langValue = lang.value(langKey);
+ if (langKey != "") {
+ langSelectBox->setCurrentIndex(langSelectBox->findText(langValue));
+ }
+
+ QString ownKeyId = settings.value("general/ownKeyId").toString();
+ qDebug() << "OwnKeyId" << ownKeyId;
+ if (ownKeyId.isEmpty()) {
+ ownKeySelectBox->setCurrentText("<none>");
+ } else {
+ const auto text = keyIds.find(ownKeyId).value();
+ qDebug() << "OwnKey" << ownKeyId << text;
+ ownKeySelectBox->setCurrentText(text);
+ }
+
+ // Get own key information from keydb/gpg.conf (if contained)
+ if (settings.value("general/confirmImportKeys", Qt::Checked).toBool()) {
+ importConfirmationCheckBox->setCheckState(Qt::Checked);
+ }
}
/***********************************
@@ -261,70 +263,72 @@ void GeneralTab::setSettings() {
* write them to settings-file
*************************************/
void GeneralTab::applySettings() {
- settings.setValue("keys/saveKeyChecked",
- saveCheckedKeysCheckBox->isChecked());
- // TODO: clear passwordCache instantly on unset rememberPassword
- settings.setValue("general/rememberPassword",
- rememberPasswordCheckBox->isChecked());
- settings.setValue("int/lang", lang.key(langSelectBox->currentText()));
- settings.setValue("general/ownKeyId",
- keyIdsList[ownKeySelectBox->currentIndex()]);
- settings.setValue("general/confirmImportKeys",
- importConfirmationCheckBox->isChecked());
+ settings.setValue("keys/saveKeyChecked",
+ saveCheckedKeysCheckBox->isChecked());
+ // TODO: clear passwordCache instantly on unset rememberPassword
+ settings.setValue("general/rememberPassword",
+ rememberPasswordCheckBox->isChecked());
+ settings.setValue("int/lang", lang.key(langSelectBox->currentText()));
+ settings.setValue("general/ownKeyId",
+ keyIdsList[ownKeySelectBox->currentIndex()]);
+ settings.setValue("general/confirmImportKeys",
+ importConfirmationCheckBox->isChecked());
}
void GeneralTab::slotLanguageChanged() { emit signalRestartNeeded(true); }
void GeneralTab::slotOwnKeyIdChanged() {
- // Set ownKeyId to currently selected
+ // Set ownKeyId to currently selected
}
-MimeTab::MimeTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- /*****************************************
- * MIME-Parsing-Box
- *****************************************/
- auto *mimeQPBox = new QGroupBox(tr("Decode quoted printable"));
- auto *mimeQPBoxLayout = new QVBoxLayout();
- mimeQPCheckBox =
- new QCheckBox(tr("Try to recognize quoted printable."), this);
- mimeQPBoxLayout->addWidget(mimeQPCheckBox);
- mimeQPBox->setLayout(mimeQPBoxLayout);
-
- auto *mimeParseBox = new QGroupBox(tr("Parse PGP/MIME (Experimental)"));
- auto *mimeParseBoxLayout = new QVBoxLayout();
- mimeParseCheckBox = new QCheckBox(
- tr("Try to split attachments from PGP-MIME ecrypted messages."), this);
- mimeParseBoxLayout->addWidget(mimeParseCheckBox);
- mimeParseBox->setLayout(mimeParseBoxLayout);
-
- auto *mimeOpenAttachmentBox =
- new QGroupBox(tr("Open with external application (Experimental)"));
- auto *mimeOpenAttachmentBoxLayout = new QVBoxLayout();
- auto *mimeOpenAttachmentText = new QLabel(tr(
- "Open attachments with default application for the filetype.<br> "
- "There are at least two possible problems with this behaviour:"
- "<ol><li>File needs to be saved unencrypted to attachments folder.<br> "
- "Its your job to clean this folder.</li>"
- "<li>The external application may have its own temp files.</li></ol>"));
-
- // mimeOpenAttachmentBox->setDisabled(true);
- mimeOpenAttachmentCheckBox =
- new QCheckBox(tr("Enable opening with external applications."), this);
-
- mimeOpenAttachmentBoxLayout->addWidget(mimeOpenAttachmentText);
- mimeOpenAttachmentBoxLayout->addWidget(mimeOpenAttachmentCheckBox);
- mimeOpenAttachmentBox->setLayout(mimeOpenAttachmentBoxLayout);
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(mimeParseBox);
- mainLayout->addWidget(mimeOpenAttachmentBox);
- mainLayout->addWidget(mimeQPBox);
- mainLayout->addStretch(1);
- setLayout(mainLayout);
- setSettings();
+SendMailTab::SendMailTab(QWidget *parent)
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+
+ enableCheckBox = new QCheckBox(tr("Enable"));
+ enableCheckBox->setTristate(false);
+
+ smtpAddress = new QLineEdit();
+ username = new QLineEdit();
+ password = new QLineEdit();
+ password->setEchoMode(QLineEdit::Password);
+
+ portSpin = new QSpinBox();
+ portSpin->setMinimum(1);
+ portSpin->setMaximum(65535);
+ connectionTypeComboBox = new QComboBox();
+ connectionTypeComboBox->addItem("None");
+ connectionTypeComboBox->addItem("SSL");
+ connectionTypeComboBox->addItem("TLS");
+ connectionTypeComboBox->addItem("STARTTLS");
+
+ defaultSender = new QLineEdit();;
+ checkConnectionButton = new QPushButton("Check Connection");
+
+ auto layout = new QGridLayout();
+ layout->addWidget(enableCheckBox, 0, 0);
+ layout->addWidget(new QLabel(tr("SMTP Address")), 1, 0);
+ layout->addWidget(smtpAddress, 1, 1, 1, 4);
+ layout->addWidget(new QLabel(tr("Username")), 2, 0);
+ layout->addWidget(username, 2, 1, 1, 4);
+ layout->addWidget(new QLabel(tr("Password")), 3, 0);
+ layout->addWidget(password, 3, 1, 1, 4);
+ layout->addWidget(new QLabel(tr("Port")), 4, 0);
+ layout->addWidget(portSpin, 4, 1, 1, 1);
+ layout->addWidget(new QLabel(tr("Connection Security")), 5, 0);
+ layout->addWidget(connectionTypeComboBox, 5, 1, 1, 1);
+
+ layout->addWidget(new QLabel(tr("Default Sender")), 6, 0);
+ layout->addWidget(defaultSender, 6, 1, 1, 4);
+ layout->addWidget(checkConnectionButton, 7, 0);
+
+ connect(enableCheckBox, SIGNAL(stateChanged(int)), this, SLOT(slotCheckBoxSetEnableDisable(int)));
+ connect(checkConnectionButton, SIGNAL(clicked(bool)), this, SLOT(slotCheckConnection()));
+
+
+ this->setLayout(layout);
+ setSettings();
}
/**********************************
@@ -332,93 +336,180 @@ MimeTab::MimeTab(QWidget *parent)
* and set the buttons and checkboxes
* appropriately
**********************************/
-void MimeTab::setSettings() {
+void SendMailTab::setSettings() {
+
+ if (settings.value("sendMail/enable", false).toBool())
+ enableCheckBox->setCheckState(Qt::Checked);
+ else {
+ enableCheckBox->setCheckState(Qt::Unchecked);
+ smtpAddress->setDisabled(true);
+ username->setDisabled(true);
+ password->setDisabled(true);
+ portSpin->setDisabled(true);
+ connectionTypeComboBox->setDisabled(true);
+ defaultSender->setDisabled(true);
+ checkConnectionButton->setDisabled(true);
+ }
+
+ smtpAddress->setText(settings.value("sendMail/smtpAddress", QString()).toString());
+ username->setText(settings.value("sendMail/username", QString()).toString());
+ password->setText(settings.value("sendMail/password", QString()).toString());
+ portSpin->setValue(settings.value("sendMail/port", 25).toInt());
+ connectionTypeComboBox->setCurrentText(settings.value("sendMail/connectionType", "None").toString());
+ defaultSender->setText(settings.value("sendMail/defaultSender", QString()).toString());
- // MIME-Parsing
- if (settings.value("mime/parsemime").toBool())
- mimeParseCheckBox->setCheckState(Qt::Checked);
-
- // Qouted Printable
- if (settings.value("mime/parseQP", true).toBool())
- mimeQPCheckBox->setCheckState(Qt::Checked);
-
- // Open Attachments with external app
- if (settings.value("mime/openAttachment").toBool())
- mimeOpenAttachmentCheckBox->setCheckState(Qt::Checked);
}
/***********************************
* get the values of the buttons and
* write them to settings-file
*************************************/
-void MimeTab::applySettings() {
- settings.setValue("mime/parsemime", mimeParseCheckBox->isChecked());
- settings.setValue("mime/parseQP", mimeQPCheckBox->isChecked());
- settings.setValue("mime/openAttachment",
- mimeOpenAttachmentCheckBox->isChecked());
+void SendMailTab::applySettings() {
+
+ settings.setValue("sendMail/smtpAddress", smtpAddress->text());
+ settings.setValue("sendMail/username", username->text());
+ settings.setValue("sendMail/password", password->text());
+ settings.setValue("sendMail/port", portSpin->value());
+ settings.setValue("sendMail/connectionType", connectionTypeComboBox->currentText());
+ settings.setValue("sendMail/defaultSender", defaultSender->text());
+
+ settings.setValue("sendMail/enable", enableCheckBox->isChecked());
+}
+
+void SendMailTab::slotCheckConnection() {
+
+ SmtpClient::ConnectionType connectionType = SmtpClient::ConnectionType::TcpConnection;
+
+ if (connectionTypeComboBox->currentText() == "SSL") {
+ connectionType = SmtpClient::ConnectionType::SslConnection;
+ } else if (connectionTypeComboBox->currentText() == "TLS") {
+ connectionType = SmtpClient::ConnectionType::TlsConnection;
+ } else if (connectionTypeComboBox->currentText() == "STARTTLS") {
+ connectionType = SmtpClient::ConnectionType::TlsConnection;
+ } else {
+ connectionType = SmtpClient::ConnectionType::TcpConnection;
+ }
+
+ SmtpClient smtp(smtpAddress->text(), portSpin->value(), connectionType);
+
+ // We need to set the username (your email address) and the password
+ // for smtp authentification.
+
+ smtp.setUser(username->text());
+ smtp.setPassword(password->text());
+
+ bool if_success = true;
+
+ if (!smtp.connectToHost()) {
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Connect SMTP Server"));
+ if_success = false;
+ }
+ if (if_success && !smtp.login()) {
+ QMessageBox::critical(this, tr("Fail"), tr("Fail to Login"));
+ if_success = false;
+ }
+
+ if (if_success)
+ QMessageBox::information(this, tr("Success"), tr("Succeed in connecting and login"));
+
+}
+
+void SendMailTab::slotCheckBoxSetEnableDisable(int state) {
+ if (state == Qt::Checked) {
+ smtpAddress->setEnabled(true);
+ username->setEnabled(true);
+ password->setEnabled(true);
+ portSpin->setEnabled(true);
+ connectionTypeComboBox->setEnabled(true);
+ defaultSender->setEnabled(true);
+ checkConnectionButton->setEnabled(true);
+ } else {
+ smtpAddress->setDisabled(true);
+ username->setDisabled(true);
+ password->setDisabled(true);
+ portSpin->setDisabled(true);
+ connectionTypeComboBox->setDisabled(true);
+ defaultSender->setDisabled(true);
+ checkConnectionButton->setDisabled(true);
+ }
}
AppearanceTab::AppearanceTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- /*****************************************
- * Icon-Size-Box
- *****************************************/
- auto *iconSizeBox = new QGroupBox(tr("Iconsize"));
- iconSizeGroup = new QButtonGroup();
- iconSizeSmall = new QRadioButton(tr("small"));
- iconSizeMedium = new QRadioButton(tr("medium"));
- iconSizeLarge = new QRadioButton(tr("large"));
-
- iconSizeGroup->addButton(iconSizeSmall, 1);
- iconSizeGroup->addButton(iconSizeMedium, 2);
- iconSizeGroup->addButton(iconSizeLarge, 3);
-
- auto *iconSizeBoxLayout = new QHBoxLayout();
- iconSizeBoxLayout->addWidget(iconSizeSmall);
- iconSizeBoxLayout->addWidget(iconSizeMedium);
- iconSizeBoxLayout->addWidget(iconSizeLarge);
-
- iconSizeBox->setLayout(iconSizeBoxLayout);
-
- /*****************************************
- * Icon-Style-Box
- *****************************************/
- auto *iconStyleBox = new QGroupBox(tr("Iconstyle"));
- iconStyleGroup = new QButtonGroup();
- iconTextButton = new QRadioButton(tr("just text"));
- iconIconsButton = new QRadioButton(tr("just icons"));
- iconAllButton = new QRadioButton(tr("text and icons"));
-
- iconStyleGroup->addButton(iconTextButton, 1);
- iconStyleGroup->addButton(iconIconsButton, 2);
- iconStyleGroup->addButton(iconAllButton, 3);
-
- auto *iconStyleBoxLayout = new QHBoxLayout();
- iconStyleBoxLayout->addWidget(iconTextButton);
- iconStyleBoxLayout->addWidget(iconIconsButton);
- iconStyleBoxLayout->addWidget(iconAllButton);
-
- iconStyleBox->setLayout(iconStyleBoxLayout);
-
- /*****************************************
- * Window-Size-Box
- *****************************************/
- auto *windowSizeBox = new QGroupBox(tr("Windowstate"));
- auto *windowSizeBoxLayout = new QHBoxLayout();
- windowSizeCheckBox =
- new QCheckBox(tr("Save window size and position on exit."), this);
- windowSizeBoxLayout->addWidget(windowSizeCheckBox);
- windowSizeBox->setLayout(windowSizeBoxLayout);
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(iconSizeBox);
- mainLayout->addWidget(iconStyleBox);
- mainLayout->addWidget(windowSizeBox);
- mainLayout->addStretch(1);
- setSettings();
- setLayout(mainLayout);
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+ /*****************************************
+ * Icon-Size-Box
+ *****************************************/
+ auto *iconSizeBox = new QGroupBox(tr("Iconsize"));
+ iconSizeGroup = new QButtonGroup();
+ iconSizeSmall = new QRadioButton(tr("small"));
+ iconSizeMedium = new QRadioButton(tr("medium"));
+ iconSizeLarge = new QRadioButton(tr("large"));
+
+ iconSizeGroup->addButton(iconSizeSmall, 1);
+ iconSizeGroup->addButton(iconSizeMedium, 2);
+ iconSizeGroup->addButton(iconSizeLarge, 3);
+
+ auto *iconSizeBoxLayout = new QHBoxLayout();
+ iconSizeBoxLayout->addWidget(iconSizeSmall);
+ iconSizeBoxLayout->addWidget(iconSizeMedium);
+ iconSizeBoxLayout->addWidget(iconSizeLarge);
+
+ iconSizeBox->setLayout(iconSizeBoxLayout);
+
+ /*****************************************
+ * Icon-Style-Box
+ *****************************************/
+ auto *iconStyleBox = new QGroupBox(tr("Iconstyle"));
+ iconStyleGroup = new QButtonGroup();
+ iconTextButton = new QRadioButton(tr("just text"));
+ iconIconsButton = new QRadioButton(tr("just icons"));
+ iconAllButton = new QRadioButton(tr("text and icons"));
+
+ iconStyleGroup->addButton(iconTextButton, 1);
+ iconStyleGroup->addButton(iconIconsButton, 2);
+ iconStyleGroup->addButton(iconAllButton, 3);
+
+ auto *iconStyleBoxLayout = new QHBoxLayout();
+ iconStyleBoxLayout->addWidget(iconTextButton);
+ iconStyleBoxLayout->addWidget(iconIconsButton);
+ iconStyleBoxLayout->addWidget(iconAllButton);
+
+ iconStyleBox->setLayout(iconStyleBoxLayout);
+
+ /*****************************************
+ * Window-Size-Box
+ *****************************************/
+ auto *windowSizeBox = new QGroupBox(tr("Windowstate"));
+ auto *windowSizeBoxLayout = new QHBoxLayout();
+ windowSizeCheckBox =
+ new QCheckBox(tr("Save window size and position on exit."), this);
+ windowSizeBoxLayout->addWidget(windowSizeCheckBox);
+ windowSizeBox->setLayout(windowSizeBoxLayout);
+
+ /*****************************************
+ * Info-Board-Font-Size-Box
+ *****************************************/
+
+ auto *infoBoardBox = new QGroupBox(tr("Information Board"));
+ auto *infoBoardLayout = new QHBoxLayout();
+ infoBoardFontSizeSpin = new QSpinBox();
+ infoBoardFontSizeSpin->setRange(9, 18);
+ infoBoardFontSizeSpin->setValue(10);
+ infoBoardFontSizeSpin->setSingleStep(1);
+ infoBoardLayout->addWidget(new QLabel(tr(" Front Size")));
+ infoBoardLayout->addWidget(infoBoardFontSizeSpin);
+ infoBoardBox->setLayout(infoBoardLayout);
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(iconSizeBox);
+ mainLayout->addWidget(iconStyleBox);
+ mainLayout->addWidget(windowSizeBox);
+ mainLayout->addWidget(infoBoardBox);
+ mainLayout->addStretch(1);
+ setSettings();
+ setLayout(mainLayout);
}
/**********************************
@@ -428,40 +519,46 @@ AppearanceTab::AppearanceTab(QWidget *parent)
**********************************/
void AppearanceTab::setSettings() {
- // Iconsize
- QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
- switch (iconSize.height()) {
- case 12:
- iconSizeSmall->setChecked(true);
- break;
- case 24:
- iconSizeMedium->setChecked(true);
- break;
- case 32:
- iconSizeLarge->setChecked(true);
- break;
- }
- // Iconstyle
- Qt::ToolButtonStyle iconStyle = static_cast<Qt::ToolButtonStyle>(
- settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
- .toUInt());
- switch (iconStyle) {
- case Qt::ToolButtonTextOnly:
- iconTextButton->setChecked(true);
- break;
- case Qt::ToolButtonIconOnly:
- iconIconsButton->setChecked(true);
- break;
- case Qt::ToolButtonTextUnderIcon:
- iconAllButton->setChecked(true);
- break;
- default:
- break;
- }
-
- // Window Save and Position
- if (settings.value("window/windowSave").toBool())
- windowSizeCheckBox->setCheckState(Qt::Checked);
+ // Iconsize
+ QSize iconSize = settings.value("toolbar/iconsize", QSize(24, 24)).toSize();
+ switch (iconSize.height()) {
+ case 12:
+ iconSizeSmall->setChecked(true);
+ break;
+ case 24:
+ iconSizeMedium->setChecked(true);
+ break;
+ case 32:
+ iconSizeLarge->setChecked(true);
+ break;
+ }
+ // Iconstyle
+ Qt::ToolButtonStyle iconStyle = static_cast<Qt::ToolButtonStyle>(
+ settings.value("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon)
+ .toUInt());
+ switch (iconStyle) {
+ case Qt::ToolButtonTextOnly:
+ iconTextButton->setChecked(true);
+ break;
+ case Qt::ToolButtonIconOnly:
+ iconIconsButton->setChecked(true);
+ break;
+ case Qt::ToolButtonTextUnderIcon:
+ iconAllButton->setChecked(true);
+ break;
+ default:
+ break;
+ }
+
+ // Window Save and Position
+ if (settings.value("window/windowSave").toBool())
+ windowSizeCheckBox->setCheckState(Qt::Checked);
+
+ // infoBoardFontSize
+ auto infoBoardFontSize = settings.value("informationBoard/fontSize", 10).toInt();
+ if (infoBoardFontSize < 9 || infoBoardFontSize > 18)
+ infoBoardFontSize = 10;
+ infoBoardFontSizeSpin->setValue(infoBoardFontSize);
}
/***********************************
@@ -469,72 +566,74 @@ void AppearanceTab::setSettings() {
* write them to settings-file
*************************************/
void AppearanceTab::applySettings() {
- switch (iconSizeGroup->checkedId()) {
- case 1:
- settings.setValue("toolbar/iconsize", QSize(12, 12));
- break;
- case 2:
- settings.setValue("toolbar/iconsize", QSize(24, 24));
- break;
- case 3:
- settings.setValue("toolbar/iconsize", QSize(32, 32));
- break;
- }
-
- switch (iconStyleGroup->checkedId()) {
- case 1:
- settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextOnly);
- break;
- case 2:
- settings.setValue("toolbar/iconstyle", Qt::ToolButtonIconOnly);
- break;
- case 3:
- settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon);
- break;
- }
-
- settings.setValue("window/windowSave", windowSizeCheckBox->isChecked());
+ switch (iconSizeGroup->checkedId()) {
+ case 1:
+ settings.setValue("toolbar/iconsize", QSize(12, 12));
+ break;
+ case 2:
+ settings.setValue("toolbar/iconsize", QSize(24, 24));
+ break;
+ case 3:
+ settings.setValue("toolbar/iconsize", QSize(32, 32));
+ break;
+ }
+
+ switch (iconStyleGroup->checkedId()) {
+ case 1:
+ settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextOnly);
+ break;
+ case 2:
+ settings.setValue("toolbar/iconstyle", Qt::ToolButtonIconOnly);
+ break;
+ case 3:
+ settings.setValue("toolbar/iconstyle", Qt::ToolButtonTextUnderIcon);
+ break;
+ }
+
+ settings.setValue("window/windowSave", windowSizeCheckBox->isChecked());
+
+ settings.setValue("informationBoard/fontSize", infoBoardFontSizeSpin->value());
}
KeyserverTab::KeyserverTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
-
- auto keyServerList = settings.value("keyserver/keyServerList").toStringList();
-
- auto *mainLayout = new QVBoxLayout(this);
-
- auto *label = new QLabel(tr("Default Keyserver for import:"));
- comboBox = new QComboBox;
- comboBox->setEditable(false);
- comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
-
- for (const auto &keyServer : keyServerList) {
- comboBox->addItem(keyServer);
- qDebug() << "KeyserverTab Get ListItemText" << keyServer;
- }
-
- comboBox->setCurrentText(
- settings.value("keyserver/defaultKeyServer").toString());
-
- auto *addKeyServerBox = new QWidget(this);
- auto *addKeyServerLayout = new QHBoxLayout(addKeyServerBox);
- auto *http = new QLabel("URL: ");
- newKeyServerEdit = new QLineEdit(this);
- auto *newKeyServerButton = new QPushButton(tr("Add"), this);
- connect(newKeyServerButton, SIGNAL(clicked()), this, SLOT(addKeyServer()));
- addKeyServerLayout->addWidget(http);
- addKeyServerLayout->addWidget(newKeyServerEdit);
- addKeyServerLayout->addWidget(newKeyServerButton);
-
- mainLayout->addWidget(label);
- mainLayout->addWidget(comboBox);
- mainLayout->addWidget(addKeyServerBox);
- mainLayout->addStretch(1);
-
- // Read keylist from ini-file and fill it into combobox
- setSettings();
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+
+ auto keyServerList = settings.value("keyserver/keyServerList").toStringList();
+
+ auto *mainLayout = new QVBoxLayout(this);
+
+ auto *label = new QLabel(tr("Default Key Server for import:"));
+ comboBox = new QComboBox;
+ comboBox->setEditable(false);
+ comboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+ for (const auto &keyServer : keyServerList) {
+ comboBox->addItem(keyServer);
+ qDebug() << "KeyserverTab Get ListItemText" << keyServer;
+ }
+
+ comboBox->setCurrentText(
+ settings.value("keyserver/defaultKeyServer").toString());
+
+ auto *addKeyServerBox = new QWidget(this);
+ auto *addKeyServerLayout = new QHBoxLayout(addKeyServerBox);
+ auto *http = new QLabel("URL: ");
+ newKeyServerEdit = new QLineEdit(this);
+ auto *newKeyServerButton = new QPushButton(tr("Add"), this);
+ connect(newKeyServerButton, SIGNAL(clicked()), this, SLOT(addKeyServer()));
+ addKeyServerLayout->addWidget(http);
+ addKeyServerLayout->addWidget(newKeyServerEdit);
+ addKeyServerLayout->addWidget(newKeyServerButton);
+
+ mainLayout->addWidget(label);
+ mainLayout->addWidget(comboBox);
+ mainLayout->addWidget(addKeyServerBox);
+ mainLayout->addStretch(1);
+
+ // Read keylist from ini-file and fill it into combobox
+ setSettings();
}
/**********************************
@@ -543,23 +642,23 @@ KeyserverTab::KeyserverTab(QWidget *parent)
* appropriately
**********************************/
void KeyserverTab::setSettings() {
- auto *keyServerList = new QStringList();
- for (int i = 0; i < comboBox->count(); i++) {
- keyServerList->append(comboBox->itemText(i));
- qDebug() << "KeyserverTab ListItemText" << comboBox->itemText(i);
- }
- settings.setValue("keyserver/keyServerList", *keyServerList);
- settings.setValue("keyserver/defaultKeyServer", comboBox->currentText());
+ auto *keyServerList = new QStringList();
+ for (int i = 0; i < comboBox->count(); i++) {
+ keyServerList->append(comboBox->itemText(i));
+ qDebug() << "KeyserverTab ListItemText" << comboBox->itemText(i);
+ }
+ settings.setValue("keyserver/keyServerList", *keyServerList);
+ settings.setValue("keyserver/defaultKeyServer", comboBox->currentText());
}
void KeyserverTab::addKeyServer() {
- if (newKeyServerEdit->text().startsWith("http://") ||
- newKeyServerEdit->text().startsWith("https://")) {
- comboBox->addItem(newKeyServerEdit->text());
- } else {
- comboBox->addItem("http://" + newKeyServerEdit->text());
- }
- comboBox->setCurrentIndex(comboBox->count() - 1);
+ if (newKeyServerEdit->text().startsWith("http://") ||
+ newKeyServerEdit->text().startsWith("https://")) {
+ comboBox->addItem(newKeyServerEdit->text());
+ } else {
+ comboBox->addItem("http://" + newKeyServerEdit->text());
+ }
+ comboBox->setCurrentIndex(comboBox->count() - 1);
}
/***********************************
@@ -567,112 +666,112 @@ void KeyserverTab::addKeyServer() {
* write them to settings-file
*************************************/
void KeyserverTab::applySettings() {
- settings.setValue("keyserver/defaultKeyServer", comboBox->currentText());
+ settings.setValue("keyserver/defaultKeyServer", comboBox->currentText());
}
AdvancedTab::AdvancedTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- /*****************************************
- * Steganography Box
- *****************************************/
- auto *steganoBox = new QGroupBox(tr("Show Steganography Options [Advanced]"));
- auto *steganoBoxLayout = new QHBoxLayout();
- steganoCheckBox = new QCheckBox(tr("Show Steganographic Options."), this);
- steganoBoxLayout->addWidget(steganoCheckBox);
- steganoBox->setLayout(steganoBoxLayout);
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(steganoBox);
- setSettings();
- mainLayout->addStretch(1);
- setLayout(mainLayout);
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+ /*****************************************
+ * Steganography Box
+ *****************************************/
+ auto *steganoBox = new QGroupBox(tr("Show Steganography Options [Advanced]"));
+ auto *steganoBoxLayout = new QHBoxLayout();
+ steganoCheckBox = new QCheckBox(tr("Show Steganographic Options."), this);
+ steganoBoxLayout->addWidget(steganoCheckBox);
+ steganoBox->setLayout(steganoBoxLayout);
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(steganoBox);
+ setSettings();
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
}
void AdvancedTab::setSettings() {
- if (settings.value("advanced/steganography").toBool()) {
- steganoCheckBox->setCheckState(Qt::Checked);
- }
+ if (settings.value("advanced/steganography").toBool()) {
+ steganoCheckBox->setCheckState(Qt::Checked);
+ }
}
void AdvancedTab::applySettings() {
- settings.setValue("advanced/steganography", steganoCheckBox->isChecked());
+ settings.setValue("advanced/steganography", steganoCheckBox->isChecked());
}
GpgPathsTab::GpgPathsTab(QWidget *parent)
- : QWidget(parent), appPath(qApp->applicationDirPath()),
- settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
- QSettings::IniFormat) {
- setSettings();
-
- /*****************************************
- * Keydb Box
- *****************************************/
- auto *keydbBox = new QGroupBox(tr("Relative path to keydb"));
- auto *keydbBoxLayout = new QGridLayout();
-
- // Label containing the current keydbpath relative to default keydb path
- keydbLabel = new QLabel(accKeydbPath, this);
-
- auto *keydbButton = new QPushButton("Change keydb path", this);
- connect(keydbButton, SIGNAL(clicked()), this, SLOT(chooseKeydbDir()));
- auto *keydbDefaultButton = new QPushButton("Set keydb to default path", this);
- connect(keydbDefaultButton, SIGNAL(clicked()), this,
- SLOT(setKeydbPathToDefault()));
-
- keydbBox->setLayout(keydbBoxLayout);
- keydbBoxLayout->addWidget(new QLabel(tr("Current keydb path: ")), 1, 1);
- keydbBoxLayout->addWidget(keydbLabel, 1, 2);
- keydbBoxLayout->addWidget(keydbButton, 1, 3);
- keydbBoxLayout->addWidget(keydbDefaultButton, 2, 3);
- keydbBoxLayout->addWidget(
- new QLabel(tr("<b>NOTE: </b> Gpg4usb will restart automatically if you "
- "change the keydb path!")),
- 3, 1, 1, 3);
-
- auto *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(keydbBox);
- mainLayout->addStretch(1);
- setLayout(mainLayout);
+ : QWidget(parent), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
+ setSettings();
+
+ /*****************************************
+ * Keydb Box
+ *****************************************/
+ auto *keydbBox = new QGroupBox(tr("Relative path to keydb"));
+ auto *keydbBoxLayout = new QGridLayout();
+
+ // Label containing the current keydbpath relative to default keydb path
+ keydbLabel = new QLabel(accKeydbPath, this);
+
+ auto *keydbButton = new QPushButton("Change keydb path", this);
+ connect(keydbButton, SIGNAL(clicked()), this, SLOT(chooseKeydbDir()));
+ auto *keydbDefaultButton = new QPushButton("Set keydb to default path", this);
+ connect(keydbDefaultButton, SIGNAL(clicked()), this,
+ SLOT(setKeydbPathToDefault()));
+
+ keydbBox->setLayout(keydbBoxLayout);
+ keydbBoxLayout->addWidget(new QLabel(tr("Current keydb path: ")), 1, 1);
+ keydbBoxLayout->addWidget(keydbLabel, 1, 2);
+ keydbBoxLayout->addWidget(keydbButton, 1, 3);
+ keydbBoxLayout->addWidget(keydbDefaultButton, 2, 3);
+ keydbBoxLayout->addWidget(
+ new QLabel(tr("<b>NOTE: </b> Gpg4usb will restart automatically if you "
+ "change the keydb path!")),
+ 3, 1, 1, 3);
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(keydbBox);
+ mainLayout->addStretch(1);
+ setLayout(mainLayout);
}
QString GpgPathsTab::getRelativePath(const QString &dir1, const QString &dir2) {
- QDir dir(dir1);
- QString s;
-
- s = dir.relativeFilePath(dir2);
- qDebug() << "relative path: " << s;
- if (s.isEmpty()) {
- s = ".";
- }
- return s;
+ QDir dir(dir1);
+ QString s;
+
+ s = dir.relativeFilePath(dir2);
+ qDebug() << "relative path: " << s;
+ if (s.isEmpty()) {
+ s = ".";
+ }
+ return s;
}
void GpgPathsTab::setKeydbPathToDefault() {
- accKeydbPath = ".";
- keydbLabel->setText(".");
+ accKeydbPath = ".";
+ keydbLabel->setText(".");
}
QString GpgPathsTab::chooseKeydbDir() {
- QString dir = QFileDialog::getExistingDirectory(
- this, tr("Choose keydb directory"), accKeydbPath,
- QFileDialog::ShowDirsOnly);
+ QString dir = QFileDialog::getExistingDirectory(
+ this, tr("Choose keydb directory"), accKeydbPath,
+ QFileDialog::ShowDirsOnly);
- accKeydbPath = getRelativePath(defKeydbPath, dir);
- keydbLabel->setText(accKeydbPath);
- return "";
+ accKeydbPath = getRelativePath(defKeydbPath, dir);
+ keydbLabel->setText(accKeydbPath);
+ return "";
}
void GpgPathsTab::setSettings() {
- defKeydbPath = qApp->applicationDirPath() + "/keydb";
+ defKeydbPath = qApp->applicationDirPath() + "/keydb";
- accKeydbPath = settings.value("gpgpaths/keydbpath").toString();
- if (accKeydbPath.isEmpty()) {
- accKeydbPath = ".";
- }
+ accKeydbPath = settings.value("gpgpaths/keydbpath").toString();
+ if (accKeydbPath.isEmpty()) {
+ accKeydbPath = ".";
+ }
}
void GpgPathsTab::applySettings() {
- settings.setValue("gpgpaths/keydbpath", accKeydbPath);
+ settings.setValue("gpgpaths/keydbpath", accKeydbPath);
}
diff --git a/src/ui/WaitingDialog.cpp b/src/ui/WaitingDialog.cpp
index 8281385a..daccc3ca 100644
--- a/src/ui/WaitingDialog.cpp
+++ b/src/ui/WaitingDialog.cpp
@@ -1,15 +1,20 @@
#include "ui/WaitingDialog.h"
-WaitingDialog::WaitingDialog(QWidget *parent) : QDialog(parent) {
+WaitingDialog::WaitingDialog(const QString &title, QWidget *parent) : QDialog(parent) {
auto *pb = new QProgressBar();
pb->setRange(0, 0);
+ pb->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ pb->setTextVisible(false);
auto *layout = new QVBoxLayout();
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
layout->addWidget(pb);
this->setLayout(layout);
this->setModal(true);
- this->setWindowTitle(tr("Processing"));
+ this->setWindowFlags(Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
+ this->setWindowTitle(title);
this->setFixedSize(240, 42);
this->show();
}
diff --git a/src/ui/Wizard.cpp b/src/ui/Wizard.cpp
index 456e8c52..b0486cc9 100644
--- a/src/ui/Wizard.cpp
+++ b/src/ui/Wizard.cpp
@@ -108,16 +108,20 @@ bool Wizard::importPubAndSecKeysFromDir(const QString &dir, KeyMgmt *keyMgmt) {
IntroPage::IntroPage(QWidget *parent)
: QWizardPage(parent), appPath(qApp->applicationDirPath()),
settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini", QSettings::IniFormat) {
- setTitle(tr("Getting started..."));
+ setTitle(tr("Getting Started..."));
setSubTitle(tr("... with GPGFrontend"));
- auto *topLabel = new QLabel(tr("To use GPGFrontend for decrypting and signing messages, you need a "
- "private key. The next page will help you with "
- "key generation or import.<br><br>"
- "For more information have a look at the <a href='docu_concepts.html'>concepts</a> "
- "(by clicking the link, the page will open in the main window). <br>"));
+ auto *topLabel = new QLabel(tr("Welcome to use GPGFrontend for decrypting and signing text or file!")+
+ " <br><br><a href='https://github.com/saturneric/GpgFrontend'>GpgFrontend</a> " +
+ tr("is a Powerful, Easy-to-Use, Compact, Cross-Platform, and Installation-Free OpenPGP Crypto Tool.") +
+ tr("For brief information have a look at the") + "<a href='https://saturneric.github.io/GpgFrontend/index.html#/overview'>"+
+ tr("Overview") +"</a> (" +
+ tr("by clicking the link, the page will open in the web browser") +
+ "). <br>");
+ topLabel->setTextFormat(Qt::RichText);
+ topLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ topLabel->setOpenExternalLinks(true);
topLabel->setWordWrap(true);
- // connect(topLabel, SIGNAL(linkActivated(QString)), parentWidget()->parentWidget(), SLOT(openHelp(QString)));
// QComboBox for language selection
auto *langLabel = new QLabel(tr("Choose a Language"));
@@ -126,9 +130,9 @@ IntroPage::IntroPage(QWidget *parent)
languages = SettingsDialog::listLanguages();
auto *langSelectBox = new QComboBox();
- foreach(QString l, languages) {
- langSelectBox->addItem(l);
- }
+ for(const auto &l : languages) {
+ langSelectBox->addItem(l);
+ }
// selected entry from config
QString langKey = settings.value("int/lang").toString();
QString langValue = languages.value(langKey);
@@ -162,25 +166,31 @@ ChoosePage::ChoosePage(QWidget *parent)
setSubTitle(tr("...by clicking on the appropriate link."));
auto *keygenLabel = new QLabel(tr("If you have never used GPGFrontend before and also don't own a gpg key yet you "
- "may possibly want to read how to") + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/generate-key\">"
- + tr("create a new keypair") + "</a><hr>");
+ "may possibly want to read how to") + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/generate-key\">"
+ + tr("Generate Key") + "</a><hr>");
keygenLabel->setTextFormat(Qt::RichText);
keygenLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
keygenLabel->setOpenExternalLinks(true);
keygenLabel->setWordWrap(true);
- auto *encrDecyTextLabel = new QLabel(tr("If you want to learn how to encrypt and decrypt text, you can read ")
+ auto *encrDecyTextLabel = new QLabel(tr("If you want to learn how to encrypt, decrypt, sign and verify text, you can read ")
+ "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/encrypt-decrypt-text\">"
- + tr("this document") + "</a><hr>");
+ + tr("Encrypt & Decrypt Text") + "</a> " + tr("or")
+ + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-text\">"
+ + tr("Sign & Verify Text")
+ +"</a><hr>");
encrDecyTextLabel->setTextFormat(Qt::RichText);
encrDecyTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
encrDecyTextLabel->setOpenExternalLinks(true);
encrDecyTextLabel->setWordWrap(true);
- auto *signVerifyTextLabel = new QLabel(tr("If you want to sign and verify text, you can read ")
- + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-text\">"
- + tr("this document") + "</a>");
+ auto *signVerifyTextLabel = new QLabel(tr("If you want to operate file, you can read ")
+ + "<a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/encrypt-decrypt-file\">"
+ + tr("Encrypt & Sign File") + "</a> " + tr("or")
+ + " <a href=\"https://saturneric.github.io/GpgFrontend/index.html#/manual/sign-verify-file\">"
+ + tr("Sign & Verify File")
+ +"</a><hr>");
signVerifyTextLabel->setTextFormat(Qt::RichText);
signVerifyTextLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
signVerifyTextLabel->setOpenExternalLinks(true);
diff --git a/src/ui/help/AboutDialog.cpp b/src/ui/help/AboutDialog.cpp
new file mode 100644
index 00000000..807c509d
--- /dev/null
+++ b/src/ui/help/AboutDialog.cpp
@@ -0,0 +1,215 @@
+/**
+ * This file is part of GPGFrontend.
+ *
+ * GPGFrontend is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Foobar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
+ *
+ * The initial version of the source code is inherited from gpg4usb-team.
+ * Their source code version also complies with GNU General Public License.
+ *
+ * The source code version of this software was modified and released
+ * by Saturneric<[email protected]> starting on May 12, 2021.
+ *
+ */
+
+#include "ui/help/AboutDialog.h"
+#include "GpgFrontendBuildInfo.h"
+
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+
+using namespace rapidjson;
+
+AboutDialog::AboutDialog(int defaultIndex, QWidget *parent)
+ : QDialog(parent) {
+ this->setWindowTitle(tr("About ") + qApp->applicationName());
+
+ auto *tabWidget = new QTabWidget;
+ auto *infoTab = new InfoTab();
+ auto *translatorsTab = new TranslatorsTab();
+ auto *updateTab = new UpdateTab();
+
+ tabWidget->addTab(infoTab, tr("General"));
+ tabWidget->addTab(translatorsTab, tr("Translators"));
+ tabWidget->addTab(updateTab, tr("Update"));
+
+ connect(tabWidget, &QTabWidget::currentChanged, this, [&](int index) {
+ qDebug() << "Current Index" << index;
+ if(index == 2) {
+ updateTab->getLatestVersion();
+ }
+ });
+
+ if(defaultIndex < tabWidget->count() && defaultIndex >= 0) {
+ tabWidget->setCurrentIndex(defaultIndex);
+ }
+
+ auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(close()));
+
+ auto *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(tabWidget);
+ mainLayout->addWidget(buttonBox);
+ setLayout(mainLayout);
+
+ this->exec();
+}
+
+InfoTab::InfoTab(QWidget *parent)
+ : QWidget(parent) {
+ auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
+ auto *text = new QString("<center><h2>" + qApp->applicationName() + "</h2></center>"
+ + "<center><b>" + qApp->applicationVersion() + "</b></center>"
+ + "<center>" + GIT_VERSION + "</center>"
+ + tr("<br><center>GPGFrontend is an easy-to-use, compact, cross-platform, <br>"
+ "and installation-free gpg front-end tool.<br>"
+ "It visualizes most of the common operations of gpg commands.<br>"
+ "It's licensed under the GPL v3<br><br>"
+ "<b>Developer:</b><br>"
+ "Saturneric<br><br>"
+ "If you have any questions or suggestions, raise an issue<br/>"
+ "at <a href=\"https://github.com/saturneric/GpgFrontend\">GitHub</a> or send a mail to my mailing list at <a href=\"mailto:[email protected]\">[email protected]</a>.") +
+ tr("<br><br> Built with Qt ") + qVersion()
+ + tr(" and GPGME ") + GpgME::GpgContext::getGpgmeVersion() +
+ tr("<br>Built at ") + BUILD_TIMESTAMP + "</center>");
+
+ auto *layout = new QGridLayout();
+ auto *pixmapLabel = new QLabel();
+ pixmapLabel->setPixmap(*pixmap);
+ layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+ auto *aboutLabel = new QLabel();
+ aboutLabel->setText(*text);
+ aboutLabel->setOpenExternalLinks(true);
+ layout->addWidget(aboutLabel, 1, 0, 1, -1);
+ layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
+ QSizePolicy::Fixed), 2, 1, 1, 1);
+
+ setLayout(layout);
+}
+
+TranslatorsTab::TranslatorsTab(QWidget *parent)
+ : QWidget(parent) {
+ QFile translatorsFile;
+ translatorsFile.setFileName(qApp->applicationDirPath() + "/About");
+ translatorsFile.open(QIODevice::ReadOnly);
+ QByteArray inBuffer = translatorsFile.readAll();
+
+ auto *label = new QLabel(inBuffer);
+ auto *mainLayout = new QVBoxLayout(this);
+ mainLayout->addWidget(label);
+
+ setLayout(mainLayout);
+}
+
+UpdateTab::UpdateTab(QWidget *parent) {
+ auto *pixmap = new QPixmap(":gpgfrontend-logo.png");
+ auto *layout = new QGridLayout();
+ auto *pixmapLabel = new QLabel();
+ pixmapLabel->setPixmap(*pixmap);
+ layout->addWidget(pixmapLabel, 0, 0, 1, -1, Qt::AlignCenter);
+
+ currentVersion = "v" + QString::number(VERSION_MAJOR) + "."
+ + QString::number(VERSION_MINOR) + "."
+ + QString::number(VERSION_PATCH);
+
+ auto tipsLabel = new QLabel();
+ tipsLabel->setText("<center>" +
+ tr("It is recommended that you always check the version of GpgFrontend and upgrade to the latest version.") +
+ "</center><br><center>" +
+ tr("New versions not only represent new features, but also often represent functional and security fixes.") + "</center>");
+ tipsLabel->setWordWrap(true);
+
+ currentVersionLabel = new QLabel();
+ currentVersionLabel->setText("<center>" + tr("Current Version: ") + "<b>" + currentVersion + "</b></center>");
+ currentVersionLabel->setWordWrap(true);
+
+ latestVersionLabel = new QLabel();
+ latestVersionLabel->setWordWrap(true);
+
+ upgradeLabel = new QLabel();
+ upgradeLabel->setText("<center>" +
+ tr("The current version is inconsistent with the latest version on github.") +
+ "</center><br><center>" +
+ tr("Please click <a href=\"https://github.com/saturneric/GpgFrontend/releases\">here</a> to download the latest version.") + "</center>");
+ upgradeLabel->setWordWrap(true);
+ upgradeLabel->setOpenExternalLinks(true);
+ upgradeLabel->setHidden(true);
+
+ pb = new QProgressBar();
+ pb->setRange(0, 0);
+ pb->setTextVisible(false);
+
+ layout->addWidget(tipsLabel, 1, 0, 1, -1);
+ layout->addWidget(currentVersionLabel, 2, 0, 1, -1);
+ layout->addWidget(latestVersionLabel, 3, 0, 1, -1);
+ layout->addWidget(upgradeLabel, 4, 0, 1, -1);
+ layout->addWidget(pb, 5, 0, 1, -1);
+ layout->addItem(new QSpacerItem(20, 10, QSizePolicy::Minimum,
+ QSizePolicy::Fixed), 2, 1, 1, 1);
+
+ setLayout(layout);
+}
+
+void UpdateTab::getLatestVersion() {
+
+ this->pb->setHidden(false);
+
+ qDebug() << "Try to get latest version";
+
+ QString baseUrl = "https://api.github.com/repos/saturneric/gpgfrontend/releases/latest";
+
+ auto manager = new QNetworkAccessManager(this);
+
+ QNetworkRequest request;
+ request.setUrl(QUrl(baseUrl));
+
+ QNetworkReply *replay = manager->get(request);
+
+ while(replay->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ this->pb->setHidden(true);
+
+ if(replay->error() != QNetworkReply::NoError) {
+ qDebug() << "VersionCheckThread Found Network Error";
+ auto latestVersion = "Unknown";
+ latestVersionLabel->setText("<center><b>" + tr("Latest Version From Github: ") + latestVersion + "</b></center>");
+ return;
+ }
+
+ QByteArray bytes = replay->readAll();
+
+ Document d;
+ d.Parse(bytes.constData());
+
+ QString latestVersion = d["tag_name"].GetString();
+
+ qDebug() << "Latest Version From Github" << latestVersion;
+
+ QRegularExpression re("^[vV](\\d+\\.)?(\\d+\\.)?(\\*|\\d+)");
+ QRegularExpressionMatch match = re.match(latestVersion);
+ if (match.hasMatch()) {
+ latestVersion = match.captured(0); // matched == "23 def"
+ qDebug() << "Latest Version Matched" << latestVersion;
+ } else {
+ latestVersion = "Unknown";
+ }
+
+ latestVersionLabel->setText("<center><b>" + tr("Latest Version From Github: ") + latestVersion + "</b></center>");
+
+ if(latestVersion > currentVersion) {
+ upgradeLabel->setHidden(false);
+ }
+
+}
diff --git a/src/ui/help/VersionCheckThread.cpp b/src/ui/help/VersionCheckThread.cpp
new file mode 100644
index 00000000..c7c77d1c
--- /dev/null
+++ b/src/ui/help/VersionCheckThread.cpp
@@ -0,0 +1,55 @@
+//
+// Created by Administrator on 2021/7/12.
+//
+
+#include "ui/help/VersionCheckThread.h"
+#include "GpgFrontendBuildInfo.h"
+#include "rapidjson/document.h"
+#include "rapidjson/writer.h"
+
+using namespace rapidjson;
+
+void VersionCheckThread::run() {
+ qDebug() << "Start Version Thread to get latest version from Github";
+
+ auto currentVersion = "v" + QString::number(VERSION_MAJOR) + "."
+ + QString::number(VERSION_MINOR) + "."
+ + QString::number(VERSION_PATCH);
+
+ while(mNetworkReply->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ if(mNetworkReply->error() != QNetworkReply::NoError) {
+ qDebug() << "VersionCheckThread Found Network Error";
+ return;
+ }
+
+ QByteArray bytes = mNetworkReply->readAll();
+
+ Document d;
+ d.Parse(bytes.constData());
+
+ QString latestVersion = d["tag_name"].GetString();
+
+ qDebug() << "Latest Version From Github" << latestVersion;
+
+ QRegularExpression re("^[vV](\\d+\\.)?(\\d+\\.)?(\\*|\\d+)");
+ QRegularExpressionMatch match = re.match(latestVersion);
+ if (match.hasMatch()) {
+ latestVersion = match.captured(0); // matched == "23 def"
+ qDebug() << "Latest Version Matched" << latestVersion;
+ } else {
+ latestVersion = currentVersion;
+ qDebug() << "Latest Version Unknown" << latestVersion;
+ }
+
+ if(latestVersion != currentVersion) {
+ emit upgradeVersion(currentVersion, latestVersion);
+ }
+
+}
+
+VersionCheckThread::VersionCheckThread(QNetworkReply *networkReply):mNetworkReply(networkReply) {
+
+}
diff --git a/src/ui/keygen/KeygenDialog.cpp b/src/ui/keygen/KeygenDialog.cpp
index b9fdae3f..7991ddd1 100644
--- a/src/ui/keygen/KeygenDialog.cpp
+++ b/src/ui/keygen/KeygenDialog.cpp
@@ -74,8 +74,7 @@ void KeyGenDialog::slotKeyGenAccept() {
* primary keys should have a reasonable expiration date (no more than 2 years in the future)
*/
if(dateEdit->dateTime() > QDateTime::currentDateTime().addYears(2)) {
-
- errorString.append(tr(" Expiration time no more than 2 years. "));
+ errorString.append(tr(" Expiration time no more than 2 years. \n"));
}
if (errorString.isEmpty()) {
@@ -148,7 +147,7 @@ QGroupBox *KeyGenDialog::create_key_usage_group_box() {
auto *groupBox = new QGroupBox(this);
auto *grid = new QGridLayout(this);
- groupBox->setTitle("Key Usage");
+ groupBox->setTitle(tr("Key Usage"));
auto* encrypt = new QCheckBox(tr("Encryption"), groupBox);
encrypt->setTristate(false);
diff --git a/src/ui/keygen/SubkeyGenerateThread.cpp b/src/ui/keygen/SubkeyGenerateThread.cpp
index 4f19ac1f..125f35f8 100644
--- a/src/ui/keygen/SubkeyGenerateThread.cpp
+++ b/src/ui/keygen/SubkeyGenerateThread.cpp
@@ -24,8 +24,6 @@
#include "ui/keygen/SubkeyGenerateThread.h"
-#include <utility>
-
SubkeyGenerateThread::SubkeyGenerateThread(GpgKey key, GenKeyInfo *keyGenParams, GpgME::GpgContext *ctx)
: mKey(std::move(key)), keyGenParams(keyGenParams) , mCtx(ctx) {
connect(this, &SubkeyGenerateThread::finished, this, &SubkeyGenerateThread::deleteLater);
diff --git a/src/ui/keypair_details/KeyPairDetailTab.cpp b/src/ui/keypair_details/KeyPairDetailTab.cpp
index 013d8e11..9ca4e37e 100644
--- a/src/ui/keypair_details/KeyPairDetailTab.cpp
+++ b/src/ui/keypair_details/KeyPairDetailTab.cpp
@@ -23,8 +23,10 @@
*/
#include "ui/keypair_details/KeyPairDetailTab.h"
+#include "ui/WaitingDialog.h"
-KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, QWidget *parent) : mKey(mKey), QWidget(parent) {
+KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, QWidget *parent) : mKey(mKey),
+ QWidget(parent) {
mCtx = ctx;
keyid = new QString(mKey.id);
@@ -53,8 +55,8 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
algorithmVarLabel = new QLabel();
// Show the situation that master key not exists.
- masterKeyExistVarLabel = new QLabel(mKey.has_master_key ? "Exists" : "Not Exists");
- if(!mKey.has_master_key){
+ masterKeyExistVarLabel = new QLabel(mKey.has_master_key ? tr("Exists") : tr("Not Exists"));
+ if (!mKey.has_master_key) {
auto paletteExpired = masterKeyExistVarLabel->palette();
paletteExpired.setColor(masterKeyExistVarLabel->foregroundRole(), Qt::red);
masterKeyExistVarLabel->setPalette(paletteExpired);
@@ -64,7 +66,7 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
masterKeyExistVarLabel->setPalette(paletteValid);
}
- if(mKey.expired){
+ if (mKey.expired) {
auto paletteExpired = expireVarLabel->palette();
paletteExpired.setColor(expireVarLabel->foregroundRole(), Qt::red);
expireVarLabel->setPalette(paletteExpired);
@@ -131,18 +133,27 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
auto *privKeyBox = new QGroupBox(tr("Operations"));
auto *vboxPK = new QVBoxLayout();
- auto *exportButton = new QPushButton(tr("Export Private Key (Include Subkeys)"));
+ auto *exportButton = new QPushButton(tr("Export Private Key (Include Subkey)"));
vboxPK->addWidget(exportButton);
connect(exportButton, SIGNAL(clicked()), this, SLOT(slotExportPrivateKey()));
- if(mKey.has_master_key) {
+ if (mKey.has_master_key) {
auto *editExpiresButton = new QPushButton(tr("Modify Expiration Datetime (Master Key)"));
vboxPK->addWidget(editExpiresButton);
connect(editExpiresButton, SIGNAL(clicked()), this, SLOT(slotModifyEditDatetime()));
+ auto hBoxLayout = new QHBoxLayout();
auto *keyServerOperaButton = new QPushButton(tr("Key Server Operation (Pubkey)"));
keyServerOperaButton->setStyleSheet("text-align:center;");
- vboxPK->addWidget(keyServerOperaButton);
+
+ auto *revokeCertGenButton = new QPushButton(tr("Generate Revoke Certificate"));
+ revokeCertGenButton->setDisabled(true);
+ connect(revokeCertGenButton, SIGNAL(clicked()), this, SLOT(slotGenRevokeCert()));
+
+ hBoxLayout->addWidget(keyServerOperaButton);
+ hBoxLayout->addWidget(revokeCertGenButton);
+
+ vboxPK->addLayout(hBoxLayout);
connect(keyServerOperaButton, SIGNAL(clicked()), this, SLOT(slotModifyEditDatetime()));
// Set Menu
@@ -152,8 +163,6 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
privKeyBox->setLayout(vboxPK);
mvbox->addWidget(privKeyBox);
-
-
}
if ((mKey.expired) || (mKey.revoked)) {
@@ -169,7 +178,7 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
expLabel->setText(tr("Warning: The Master Key has been revoked"));
}
- iconLabel->setPixmap(pixmap.scaled(24,24,Qt::KeepAspectRatio));
+ iconLabel->setPixmap(pixmap.scaled(24, 24, Qt::KeepAspectRatio));
QFont font = expLabel->font();
font.setBold(true);
expLabel->setFont(font);
@@ -179,10 +188,11 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
mvbox->addLayout(expBox);
}
+ mvbox->setContentsMargins(0, 0, 0, 0);
+
connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshKeyInfo()));
slotRefreshKeyInfo();
-
setAttribute(Qt::WA_DeleteOnClose, true);
setLayout(mvbox);
}
@@ -190,22 +200,23 @@ KeyPairDetailTab::KeyPairDetailTab(GpgME::GpgContext *ctx, const GpgKey &mKey, Q
void KeyPairDetailTab::slotExportPrivateKey() {
// Show a information box with explanation about private key
int ret = QMessageBox::information(this, tr("Exporting private Key"),
- tr("<h3>You are about to export your <font color=\"red\">PRIVATE KEY</font>!</h3>\n"
- "This is NOT your Public Key, so DON'T give it away.<br />"
- "Do you REALLY want to export your PRIVATE KEY?"),
+ "<h3>" + tr("You are about to export your") + "<font color=\"red\">" +
+ tr("PRIVATE KEY") + "</font>!</h3>\n" +
+ tr("This is NOT your Public Key, so DON'T give it away.") + "<br />" +
+ tr("Do you REALLY want to export your PRIVATE KEY?"),
QMessageBox::Cancel | QMessageBox::Ok);
// export key, if ok was clicked
if (ret == QMessageBox::Ok) {
auto *keyArray = new QByteArray();
- if(!mCtx->exportSecretKey(mKey, keyArray)) {
- QMessageBox::critical(this, "Error", "An error occurred during the export operation.");
- return;
- }
+ if (!mCtx->exportSecretKey(mKey, keyArray)) {
+ QMessageBox::critical(this, "Error", "An error occurred during the export operation.");
+ return;
+ }
auto &key = mCtx->getKeyById(*keyid);
- QString fileString = key.name + " " +key.email + "(" +
+ QString fileString = key.name + " " + key.email + "(" +
key.id + ")_secret.asc";
QString fileName = QFileDialog::getSaveFileName(this, tr("Export Key To File"), fileString,
tr("Key Files") + " (*.asc *.txt);;All Files (*)");
@@ -251,13 +262,13 @@ void KeyPairDetailTab::slotRefreshKeyInfo() {
QString usage;
QTextStream usage_steam(&usage);
- if(mKey.can_certify)
+ if (mKey.can_certify)
usage_steam << "Cert ";
- if(mKey.can_encrypt)
+ if (mKey.can_encrypt)
usage_steam << "Encr ";
- if(mKey.can_sign)
+ if (mKey.can_sign)
usage_steam << "Sign ";
- if(mKey.can_authenticate)
+ if (mKey.can_authenticate)
usage_steam << "Auth ";
usageVarLabel->setText(usage);
@@ -265,13 +276,13 @@ void KeyPairDetailTab::slotRefreshKeyInfo() {
QString actualUsage;
QTextStream actual_usage_steam(&actualUsage);
- if(GpgME::GpgContext::checkIfKeyCanCert(mKey))
+ if (GpgME::GpgContext::checkIfKeyCanCert(mKey))
actual_usage_steam << "Cert ";
- if(GpgME::GpgContext::checkIfKeyCanEncr(mKey))
+ if (GpgME::GpgContext::checkIfKeyCanEncr(mKey))
actual_usage_steam << "Encr ";
- if(GpgME::GpgContext::checkIfKeyCanSign(mKey))
+ if (GpgME::GpgContext::checkIfKeyCanSign(mKey))
actual_usage_steam << "Sign ";
- if(GpgME::GpgContext::checkIfKeyCanAuth(mKey))
+ if (GpgME::GpgContext::checkIfKeyCanAuth(mKey))
actual_usage_steam << "Auth ";
actualUsageVarLabel->setText(actualUsage);
@@ -301,7 +312,7 @@ void KeyPairDetailTab::slotRefreshKeyInfo() {
void KeyPairDetailTab::createKeyServerOperaMenu() {
keyServerOperaMenu = new QMenu(this);
- auto *uploadKeyPair = new QAction(tr("Upload Key Pair"), this);
+ auto *uploadKeyPair = new QAction(tr("Upload Key Pair to Key Server"), this);
connect(uploadKeyPair, SIGNAL(triggered()), this, SLOT(slotUploadKeyToServer()));
auto *updateKeyPair = new QAction(tr("Update Key Pair"), this);
connect(updateKeyPair, SIGNAL(triggered()), this, SLOT(slotUpdateKeyToServer()));
@@ -325,3 +336,21 @@ void KeyPairDetailTab::slotUpdateKeyToServer() {
dialog->slotImportKey(keys);
}
+void KeyPairDetailTab::slotGenRevokeCert() {
+ auto mOutputFileName = QFileDialog::getSaveFileName(this, tr("Generate revocation certificate"),
+ QString(),
+ QStringLiteral("%1 (*.rev)").arg(
+ tr("Revocation Certificates")));
+
+ auto process = mCtx->generateRevokeCert(mKey, mOutputFileName);
+
+ auto *dialog = new WaitingDialog("Generating", this);
+
+ while (process->state() == QProcess::Running) {
+ QApplication::processEvents();
+ }
+
+ dialog->close();
+
+}
+
diff --git a/src/ui/keypair_details/KeyPairSubkeyTab.cpp b/src/ui/keypair_details/KeyPairSubkeyTab.cpp
index 70c7e4b8..74b52284 100644
--- a/src/ui/keypair_details/KeyPairSubkeyTab.cpp
+++ b/src/ui/keypair_details/KeyPairSubkeyTab.cpp
@@ -47,6 +47,7 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW
auto subkeyListLayout = new QGridLayout();
subkeyListLayout->addWidget(subkeyList, 0, 0);
subkeyListLayout->addLayout(uidButtonsLayout, 1, 0);
+ subkeyListLayout->setContentsMargins(0, 10, 0, 0);
auto *subkeyDetailLayout = new QGridLayout();
@@ -79,6 +80,7 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW
subkeyDetailLayout->addWidget(fingerPrintVarLabel, 7, 1);
listBox->setLayout(subkeyListLayout);
+ listBox->setContentsMargins(0, 5, 0, 0);
detailBox->setLayout(subkeyDetailLayout);
baseLayout->addWidget(listBox);
@@ -89,6 +91,8 @@ KeyPairSubkeyTab::KeyPairSubkeyTab(GpgME::GpgContext *ctx, const GpgKey &key, QW
connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshSubkeyList()));
connect(subkeyList, SIGNAL(itemSelectionChanged()), this, SLOT(slotRefreshSubkeyDetail()));
+ baseLayout->setContentsMargins(0, 0, 0, 0);
+
setLayout(baseLayout);
setAttribute(Qt::WA_DeleteOnClose, true);
diff --git a/src/ui/keypair_details/KeyPairUIDTab.cpp b/src/ui/keypair_details/KeyPairUIDTab.cpp
index 51f188bd..2954aadb 100644
--- a/src/ui/keypair_details/KeyPairUIDTab.cpp
+++ b/src/ui/keypair_details/KeyPairUIDTab.cpp
@@ -52,21 +52,24 @@ KeyPairUIDTab::KeyPairUIDTab(GpgME::GpgContext *ctx, const GpgKey &key, QWidget
gridLayout->addWidget(uidList, 0, 0);
gridLayout->addLayout(uidButtonsLayout, 1, 0);
+ gridLayout->setContentsMargins(0, 10, 0, 0);
auto uidGroupBox = new QGroupBox();
uidGroupBox->setLayout(gridLayout);
- uidGroupBox->setTitle("UIDs");
+ uidGroupBox->setTitle(tr("UIDs"));
auto signGridLayout = new QGridLayout();
signGridLayout->addWidget(sigList, 0, 0);
+ signGridLayout->setContentsMargins(0, 10, 0, 0);
auto signGroupBox = new QGroupBox();
signGroupBox->setLayout(signGridLayout);
- signGroupBox->setTitle("Signature of Selected UID");
+ signGroupBox->setTitle(tr("Signature of Selected UID"));
auto vboxLayout = new QVBoxLayout();
vboxLayout->addWidget(uidGroupBox);
vboxLayout->addWidget(signGroupBox);
+ vboxLayout->setContentsMargins(0, 0, 0, 0);
connect(addUIDButton, SIGNAL(clicked(bool)), this, SLOT(slotAddUID()));
connect(mCtx, SIGNAL(signalKeyInfoChanged()), this, SLOT(slotRefreshUIDList()));
diff --git a/src/ui/main_window/MainWindowSlotFunction.cpp b/src/ui/main_window/MainWindowSlotFunction.cpp
index 36d8f363..4bcee080 100644
--- a/src/ui/main_window/MainWindowSlotFunction.cpp
+++ b/src/ui/main_window/MainWindowSlotFunction.cpp
@@ -23,6 +23,7 @@
*/
#include "MainWindow.h"
+#include "ui/SendMailDialog.h"
void MainWindow::slotEncrypt() {
@@ -58,12 +59,12 @@ void MainWindow::slotEncrypt() {
auto thread = QThread::create([&]() {
error = mCtx->encrypt(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, &result);
});
-
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
+ auto *dialog = new WaitingDialog(tr("Encrypting"), this);
- while(thread->isRunning()) {
+ while (thread->isRunning()) {
QApplication::processEvents();
}
@@ -83,6 +84,19 @@ void MainWindow::slotEncrypt() {
else
infoBoard->slotRefresh(reportText, INFO_ERROR_WARN);
+ if (resultAnalyse->getStatus() >= 0) {
+ infoBoard->resetOptionActionsMenu();
+ infoBoard->addOptionalAction("Send Mail", [this]() {
+ if(settings.value("sendMail/enable", false).toBool())
+ new SendMailDialog(edit->curTextPage()->toPlainText(), this);
+ else {
+ QMessageBox::warning(nullptr,
+ tr("Function Disabled"),
+ tr("Please go to the settings interface to enable and configure this function."));
+ }
+ });
+ }
+
delete resultAnalyse;
} else if (edit->slotCurPageFileTreeView() != nullptr) {
this->slotFileEncrypt();
@@ -118,7 +132,19 @@ void MainWindow::slotSign() {
gpgme_sign_result_t result = nullptr;
- auto error = mCtx->sign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, false, &result);
+ gpgme_error_t error;
+ auto thread = QThread::create([&]() {
+ error = mCtx->sign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, false, &result);
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
+
+ auto *dialog = new WaitingDialog(tr("Signing"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+ dialog->close();
+
infoBoard->associateTextEdit(edit->curTextPage());
edit->slotFillTextEditWithText(QString::fromUtf8(*tmp));
@@ -154,10 +180,11 @@ void MainWindow::slotDecrypt() {
// try decrypt, if fail do nothing, especially don't replace text
error = mCtx->decrypt(text, decrypted, &result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Decrypting"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
@@ -213,13 +240,13 @@ void MainWindow::slotVerify() {
auto thread = QThread::create([&]() {
error = mCtx->verify(&text, nullptr, &result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Verifying"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
-
dialog->close();
auto resultAnalyse = new VerifyResultAnalyse(mCtx, error, result);
@@ -268,27 +295,27 @@ void MainWindow::slotEncryptSign() {
if (!key_can_sign && !key_can_encr) {
QMessageBox::critical(nullptr,
- tr("Invalid KeyPair"),
- tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>")
- + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid);
+ tr("Invalid KeyPair"),
+ tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>")
+ + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid);
return;
}
- if(key_can_sign) can_sign = true;
- if(key_can_encr) can_encr = true;
+ if (key_can_sign) can_sign = true;
+ if (key_can_encr) can_encr = true;
}
- if(!can_encr) {
- QMessageBox::critical(nullptr,
- tr("Incomplete Operation"),
- tr("None of the selected key pairs can provide the encryption function."));
- return;
+ if (!can_encr) {
+ QMessageBox::critical(nullptr,
+ tr("Incomplete Operation"),
+ tr("None of the selected key pairs can provide the encryption function."));
+ return;
}
- if(!can_sign) {
- QMessageBox::warning(nullptr,
- tr("Incomplete Operation"),
- tr("None of the selected key pairs can provide the signature function."));
+ if (!can_sign) {
+ QMessageBox::warning(nullptr,
+ tr("Incomplete Operation"),
+ tr("None of the selected key pairs can provide the signature function."));
}
auto *tmp = new QByteArray();
@@ -300,18 +327,19 @@ void MainWindow::slotEncryptSign() {
gpgme_error_t error;
auto thread = QThread::create([&]() {
error = mCtx->encryptSign(keys, edit->curTextPage()->toPlainText().toUtf8(), tmp, &encr_result,
- &sign_result);
+ &sign_result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Encrypting and Signing"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
dialog->close();
- if(gpgme_err_code(error) == GPG_ERR_NO_ERROR) {
+ if (gpgme_err_code(error) == GPG_ERR_NO_ERROR) {
auto *tmp2 = new QString(*tmp);
edit->slotFillTextEditWithText(*tmp2);
}
@@ -330,6 +358,19 @@ void MainWindow::slotEncryptSign() {
else
infoBoard->slotRefresh(reportText, INFO_ERROR_WARN);
+ if (status >= 0) {
+ infoBoard->resetOptionActionsMenu();
+ infoBoard->addOptionalAction("Send Mail", [this]() {
+ if(settings.value("sendMail/enable", false).toBool())
+ new SendMailDialog(edit->curTextPage()->toPlainText(), this);
+ else {
+ QMessageBox::warning(nullptr,
+ tr("Function Disabled"),
+ tr("Please go to the settings interface to enable and configure this function."));
+ }
+ });
+ }
+
delete resultAnalyseEncr;
delete resultAnalyseSign;
} else if (edit->slotCurPageFileTreeView() != nullptr) {
@@ -354,10 +395,11 @@ void MainWindow::slotDecryptVerify() {
auto thread = QThread::create([&]() {
error = mCtx->decryptVerify(text, decrypted, &d_result, &v_result);
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Decrypting and Verifying"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
@@ -495,22 +537,27 @@ void MainWindow::slotFileEncrypt() {
}
}
- try {
- gpgme_encrypt_result_t result;
+ gpgme_encrypt_result_t result;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
+ gpgme_error_t error;
+ bool if_error = false;
+ auto thread = QThread::create([&]() {
+ try {
error = GpgFileOpera::encryptFile(mCtx, keys, path, &result);
- });
- thread->start();
-
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
- dialog->close();
+ auto *dialog = new WaitingDialog(tr("Encrypting"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+ dialog->close();
+ if (!if_error) {
auto resultAnalyse = new EncryptResultAnalyse(error, result);
auto &reportText = resultAnalyse->getResultReport();
infoBoard->associateTabWidget(edit->tabWidget);
@@ -526,11 +573,10 @@ void MainWindow::slotFileEncrypt() {
delete resultAnalyse;
fileTreeView->update();
-
- } catch (const std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
+ return;
}
-
}
void MainWindow::slotFileDecrypt() {
@@ -572,21 +618,28 @@ void MainWindow::slotFileDecrypt() {
return;
}
- try {
- gpgme_decrypt_result_t result;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
- error = GpgFileOpera::decryptFile(mCtx, path, &result);
- });
- thread->start();
+ gpgme_decrypt_result_t result;
+ gpgme_error_t error;
+ bool if_error = false;
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ auto thread = QThread::create([&]() {
+ try {
+ error = GpgFileOpera::decryptFile(mCtx, path, &result);
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
- dialog->close();
+ auto *dialog = new WaitingDialog("Decrypting", this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ dialog->close();
+ if (!if_error) {
auto resultAnalyse = new DecryptResultAnalyse(mCtx, error, result);
auto &reportText = resultAnalyse->getResultReport();
infoBoard->associateTabWidget(edit->tabWidget);
@@ -602,7 +655,7 @@ void MainWindow::slotFileDecrypt() {
delete resultAnalyse;
fileTreeView->update();
- } catch (const std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
return;
}
@@ -661,20 +714,28 @@ void MainWindow::slotFileSign() {
}
}
- try {
- gpgme_sign_result_t result;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
- error = GpgFileOpera::signFile(mCtx, keys, path, &result);
- });
- thread->start();
+ gpgme_sign_result_t result;
+ gpgme_error_t error;
+ bool if_error = false;
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ auto thread = QThread::create([&]() {
+ try {
+ error = GpgFileOpera::signFile(mCtx, keys, path, &result);
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
- dialog->close();
+ auto *dialog = new WaitingDialog(tr("Signing"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+
+ dialog->close();
+
+ if (!if_error) {
auto resultAnalyse = new SignResultAnalyse(error, result);
auto &reportText = resultAnalyse->getResultReport();
@@ -692,8 +753,9 @@ void MainWindow::slotFileSign() {
fileTreeView->update();
- } catch (const std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
+ return;
}
fileTreeView->update();
@@ -709,11 +771,10 @@ void MainWindow::slotFileVerify() {
QString signFilePath, dataFilePath;
- if(fileInfo.suffix() == "gpg") {
+ if (fileInfo.suffix() == "gpg") {
dataFilePath = path;
signFilePath = path;
- }
- else if (fileInfo.suffix() == "sig") {
+ } else if (fileInfo.suffix() == "sig") {
int pos = path.lastIndexOf(QChar('.'));
dataFilePath = path.left(pos);
signFilePath = path;
@@ -743,21 +804,22 @@ void MainWindow::slotFileVerify() {
gpgme_error_t error;
bool if_error = false;
auto thread = QThread::create([&]() {
- try{
+ try {
error = GpgFileOpera::verifyFile(mCtx, dataFilePath, &result);
} catch (const std::runtime_error &e) {
if_error = true;
}
});
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
thread->start();
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
+ auto *dialog = new WaitingDialog(tr("Verifying"), this);
+ while (thread->isRunning()) {
QApplication::processEvents();
}
dialog->close();
- if(!if_error) {
+ if (!if_error) {
auto resultAnalyse = new VerifyResultAnalyse(mCtx, error, result);
auto &reportText = resultAnalyse->getResultReport();
infoBoard->associateTabWidget(edit->tabWidget);
@@ -832,45 +894,52 @@ void MainWindow::slotFileEncryptSign() {
if (!key_can_sign && !key_can_encr) {
QMessageBox::critical(nullptr,
- tr("Invalid KeyPair"),
- tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>")
- + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid);
+ tr("Invalid KeyPair"),
+ tr("The selected keypair cannot be used for signing and encryption at the same time.<br/>")
+ + tr("<br/>For example the Following Key: <br/>") + key.uids.first().uid);
return;
}
- if(key_can_sign) can_sign = true;
- if(key_can_encr) can_encr = true;
+ if (key_can_sign) can_sign = true;
+ if (key_can_encr) can_encr = true;
}
- if(!can_encr) {
- QMessageBox::critical(nullptr,
- tr("Incomplete Operation"),
- tr("None of the selected key pairs can provide the encryption function."));
- return;
+ if (!can_encr) {
+ QMessageBox::critical(nullptr,
+ tr("Incomplete Operation"),
+ tr("None of the selected key pairs can provide the encryption function."));
+ return;
}
- if(!can_sign) {
- QMessageBox::warning(nullptr,
- tr("Incomplete Operation"),
- tr("None of the selected key pairs can provide the signature function."));
+ if (!can_sign) {
+ QMessageBox::warning(nullptr,
+ tr("Incomplete Operation"),
+ tr("None of the selected key pairs can provide the signature function."));
}
- try {
+ gpgme_encrypt_result_t encr_result = nullptr;
+ gpgme_sign_result_t sign_result = nullptr;
- gpgme_encrypt_result_t encr_result = nullptr;
- gpgme_sign_result_t sign_result = nullptr;
+ gpgme_error_t error;
+ bool if_error = false;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
+ auto thread = QThread::create([&]() {
+ try {
error = GpgFileOpera::encryptSignFile(mCtx, keys, path, &encr_result, &sign_result);
- });
- thread->start();
-
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
- dialog->close();
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
+
+ WaitingDialog *dialog = new WaitingDialog(tr("Encrypting and Signing"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+ dialog->close();
+
+ if (!if_error) {
auto resultAnalyseEncr = new EncryptResultAnalyse(error, encr_result);
auto resultAnalyseSign = new SignResultAnalyse(error, sign_result);
@@ -891,8 +960,9 @@ void MainWindow::slotFileEncryptSign() {
fileTreeView->update();
- } catch (std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
+ return;
}
}
@@ -924,22 +994,30 @@ void MainWindow::slotFileDecryptVerify() {
outFileName = path + ".out";
}
- try {
+ gpgme_decrypt_result_t d_result = nullptr;
+ gpgme_verify_result_t v_result = nullptr;
- gpgme_decrypt_result_t d_result = nullptr;
- gpgme_verify_result_t v_result = nullptr;
+ gpgme_error_t error;
+ bool if_error = false;
- gpgme_error_t error;
- auto thread = QThread::create([&]() {
+ auto thread = QThread::create([&]() {
+ try {
error = GpgFileOpera::decryptVerifyFile(mCtx, path, &d_result, &v_result);
- });
- thread->start();
-
- WaitingDialog *dialog = new WaitingDialog(this);
- while(thread->isRunning()) {
- QApplication::processEvents();
+ } catch (const std::runtime_error &e) {
+ if_error = true;
}
- dialog->close();
+ });
+ connect(thread, SIGNAL(finished(QPrivateSignal)), thread, SLOT(deleteLater()));
+ thread->start();
+
+
+ auto *dialog = new WaitingDialog(tr("Decrypting and Verifying"), this);
+ while (thread->isRunning()) {
+ QApplication::processEvents();
+ }
+ dialog->close();
+
+ if (!if_error) {
infoBoard->associateFileTreeView(edit->curFilePage());
auto resultAnalyseDecrypt = new DecryptResultAnalyse(mCtx, error, d_result);
@@ -964,7 +1042,7 @@ void MainWindow::slotFileDecryptVerify() {
delete resultAnalyseVerify;
fileTreeView->update();
- } catch (std::runtime_error &e) {
+ } else {
QMessageBox::critical(this, tr("Error"), tr("An error occurred during operation."));
return;
}
@@ -997,3 +1075,21 @@ void MainWindow::slotFileVerifyCustom() {
void MainWindow::slotOpenFile(QString &path) {
edit->slotOpenFile(path);
}
+
+void MainWindow::slotVersionUpgrade(const QString &currentVersion, const QString &latestVersion) {
+ if(currentVersion < latestVersion) {
+ QMessageBox::warning(this,
+ tr("Outdated Version"),
+ tr("This version(%1) is out of date, please update the latest version in time. ").arg(
+ currentVersion)
+ + tr("You can download the latest version(%1) on Github Releases Page.<br/>").arg(
+ latestVersion));
+ } else if(currentVersion > latestVersion) {
+ QMessageBox::warning(this,
+ tr("Unreleased Version"),
+ tr("This version(%1) has not been officially released and is not recommended for use in a production environment. <br/>").arg(
+ currentVersion)
+ + tr("You can download the latest version(%1) on Github Releases Page.<br/>").arg(
+ latestVersion));
+ }
+}
diff --git a/src/ui/main_window/MainWindowSlotUI.cpp b/src/ui/main_window/MainWindowSlotUI.cpp
index 189ead53..7065e41c 100644
--- a/src/ui/main_window/MainWindowSlotUI.cpp
+++ b/src/ui/main_window/MainWindowSlotUI.cpp
@@ -25,7 +25,11 @@
#include "MainWindow.h"
void MainWindow::slotAbout() {
- new AboutDialog(this);
+ new AboutDialog(0, this);
+}
+
+void MainWindow::slotCheckUpdate() {
+ new AboutDialog(2, this);
}
void MainWindow::slotSetStatusBarText(const QString &text) {
@@ -141,13 +145,6 @@ void MainWindow::slotOpenSettingsDialog() {
importButton->setToolButtonStyle(buttonStyle);
fileEncButton->setToolButtonStyle(buttonStyle);
- // Mime-settings
- if (settings.value("mime/parseMime").toBool()) {
- createAttachmentDock();
- } else if (attachmentDockCreated) {
- closeAttachmentDock();
- }
-
// restart mainwindow if necessary
if (getRestartNeeded()) {
if (edit->maybeSaveAnyTab()) {
diff --git a/src/ui/main_window/MainWindowUI.cpp b/src/ui/main_window/MainWindowUI.cpp
index 233a0927..21f6e3b7 100644
--- a/src/ui/main_window/MainWindowUI.cpp
+++ b/src/ui/main_window/MainWindowUI.cpp
@@ -209,18 +209,27 @@ void MainWindow::createActions() {
importKeyFromEditAct->setToolTip(tr("Import New Key From Editor"));
connect(importKeyFromEditAct, SIGNAL(triggered()), this, SLOT(slotImportKeyFromEdit()));
- openKeyManagementAct = new QAction(tr("Manage &keys"), this);
+ openKeyManagementAct = new QAction(tr("Manage &Keys"), this);
openKeyManagementAct->setIcon(QIcon(":keymgmt.png"));
openKeyManagementAct->setToolTip(tr("Open Keymanagement"));
connect(openKeyManagementAct, SIGNAL(triggered()), this, SLOT(slotOpenKeyManagement()));
- /* About Menu
+ /*
+ * About Menu
*/
aboutAct = new QAction(tr("&About"), this);
aboutAct->setIcon(QIcon(":help.png"));
aboutAct->setToolTip(tr("Show the application's About box"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(slotAbout()));
+ /*
+ * Check Update Menu
+ */
+ checkUpdateAct = new QAction(tr("&Check for Updates"), this);
+ checkUpdateAct->setIcon(QIcon(":help.png"));
+ checkUpdateAct->setToolTip(tr("Check for updates"));
+ connect(checkUpdateAct, SIGNAL(triggered()), this, SLOT(slotCheckUpdate()));
+
startWizardAct = new QAction(tr("Open &Wizard"), this);
startWizardAct->setToolTip(tr("Open the wizard"));
connect(startWizardAct, SIGNAL(triggered()), this, SLOT(slotStartWizard()));
@@ -231,8 +240,8 @@ void MainWindow::createActions() {
appendSelectedKeysAct->setToolTip(tr("Append The Selected Keys To Text in Editor"));
connect(appendSelectedKeysAct, SIGNAL(triggered()), this, SLOT(slotAppendSelectedKeys()));
- copyMailAddressToClipboardAct = new QAction(tr("Copy EMail-address"), this);
- copyMailAddressToClipboardAct->setToolTip(tr("Copy selected EMailaddress to clipboard"));
+ copyMailAddressToClipboardAct = new QAction(tr("Copy Email"), this);
+ copyMailAddressToClipboardAct->setToolTip(tr("Copy selected Email to clipboard"));
connect(copyMailAddressToClipboardAct, SIGNAL(triggered()), this, SLOT(slotCopyMailAddressToClipboard()));
// TODO: find central place for shared actions, to avoid code-duplication with keymgmt.cpp
@@ -247,6 +256,7 @@ void MainWindow::createActions() {
uploadKeyToServerAct = new QAction(tr("Upload Public Key(s) To Server"), this);
uploadKeyToServerAct->setToolTip(tr("Upload The Selected Public Keys To Server"));
connect(uploadKeyToServerAct, SIGNAL(triggered()), this, SLOT(uploadKeyToServer()));
+
/* Key-Shortcuts for Tab-Switchung-Action
*/
switchTabUpAct = new QAction(this);
@@ -339,6 +349,7 @@ void MainWindow::createMenus() {
helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(startWizardAct);
helpMenu->addSeparator();
+ helpMenu->addAction(checkUpdateAct);
helpMenu->addAction(aboutAct);
}
@@ -436,26 +447,4 @@ void MainWindow::createDockWindows() {
infoBoardDock->setWidget(infoBoard);
infoBoardDock->widget()->layout()->setContentsMargins(0, 0, 0, 0);
viewMenu->addAction(infoBoardDock->toggleViewAction());
-
- /* Attachments-Dockwindow
- */
- if (settings.value("mime/parseMime").toBool()) {
- createAttachmentDock();
- }
-}
-
-void MainWindow::createAttachmentDock() {
- if (attachmentDockCreated) {
- return;
- }
- mAttachments = new Attachments();
- attachmentDock = new QDockWidget(tr("Attached files:"), this);
- attachmentDock->setObjectName("AttachmentDock");
- attachmentDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
- addDockWidget(Qt::LeftDockWidgetArea, attachmentDock);
- attachmentDock->setWidget(mAttachments);
- // hide till attachment is decrypted
- viewMenu->addAction(attachmentDock->toggleViewAction());
- attachmentDock->hide();
- attachmentDockCreated = true;
}
diff --git a/src/ui/widgets/Attachments.cpp b/src/ui/widgets/Attachments.cpp
deleted file mode 100644
index 8f741f66..00000000
--- a/src/ui/widgets/Attachments.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * This file is part of GPGFrontend.
- *
- * GPGFrontend is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Foobar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Foobar. If not, see <https://www.gnu.org/licenses/>.
- *
- * The initial version of the source code is inherited from gpg4usb-team.
- * Their source code version also complies with GNU General Public License.
- *
- * The source code version of this software was modified and released
- * by Saturneric<[email protected]> starting on May 12, 2021.
- *
- */
-
-/* TODO:
- * - check content encoding (base64 / quoted-printable) and apply appropriate opperation (maybe already in mime.cpp)
- * - check memory usage, use less copy operations / more references
- * - possibility to clear attachment-view , e.g. with decryption or encrypting a new message
- * - save all: like in thunderbird, one folder, all files go there
- */
-
-/*
- * - save, delete (clear) all
- * - each line save & clear button
- * - attached files to view-menu
- * - also an open button, whichs should save file to tmp-folder, and open with correct app (via QDesktopServices)
- */
-
-
-#include "ui/widgets/Attachments.h"
-
-Attachments::Attachments(QWidget *parent)
- : QWidget(parent) {
- table = new AttachmentTableModel(this);
-
- tableView = new QTableView;
- tableView->setModel(table);
- tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
- // only one entry should be selected at time
- tableView->setSelectionMode(QAbstractItemView::SingleSelection);
- tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
- tableView->setFocusPolicy(Qt::NoFocus);
- tableView->setAlternatingRowColors(true);
- tableView->verticalHeader()->hide();
- tableView->setShowGrid(false);
- tableView->setColumnWidth(0, 300);
- tableView->horizontalHeader()->setStretchLastSection(true);
-
- auto *layout = new QVBoxLayout;
- layout->addWidget(tableView);
- layout->setContentsMargins(0, 0, 0, 0);
- setLayout(layout);
- createActions();
-
-}
-
-void Attachments::contextMenuEvent(QContextMenuEvent *event) {
- QMenu menu(this);
- menu.addAction(saveFileAct);
- // enable open with only if allowed by user
- if (settings.value("mime/openAttachment").toBool())
- menu.addAction(openFileAct);
-
- menu.exec(event->globalPos());
-}
-
-void Attachments::createActions() {
- saveFileAct = new QAction(tr("Save File"), this);
- saveFileAct->setToolTip(tr("Save this file"));
- saveFileAct->setIcon(QIcon(":filesave.png"));
- connect(saveFileAct, SIGNAL(triggered()), this, SLOT(slotSaveFile()));
-
- openFileAct = new QAction(tr("Open File"), this);
- openFileAct->setToolTip(tr("Open this file"));
- openFileAct->setIcon(QIcon(":fileopen.png"));
- connect(openFileAct, SIGNAL(triggered()), this, SLOT(slotOpenFile()));
-
-}
-
-void Attachments::slotSaveFile() {
-
- QModelIndexList indexes = tableView->selectionModel()->selection().indexes();
-
- if (indexes.empty()) {
- return;
- }
-
- // only singe-selection possible now: TODO: foreach
- MimePart mp = table->getMimePart(indexes.at(0).row());
- QString filename = mp.header.getParam("Content-Type", "name");
- // TODO: find out why filename is quoted
- filename.chop(1);
- filename.remove(0, 1);
- // TODO: check if really base64
- saveByteArrayToFile(QByteArray::fromBase64(mp.body), filename);
-
-}
-
-void Attachments::saveByteArrayToFile(QByteArray outBuffer, QString filename) {
-
- //QString path="";
- QString path = std::move(filename);
- QString outfileName = QFileDialog::getSaveFileName(this, tr("Save File"), path);
-
- if (outfileName.isEmpty()) return;
-
- QFile outfile(outfileName);
- if (!outfile.open(QFile::WriteOnly)) {
- QMessageBox::warning(this, tr("File"),
- tr("Cannot write file %1:\n%2.")
- .arg(outfileName)
- .arg(outfile.errorString()));
- return;
- }
-
- QDataStream out(&outfile);
- out.writeRawData(outBuffer.data(), outBuffer.length());
- outfile.close();
-}
-
-/**
- * WIP: TODO:
- * - create attachments dir if not existing
- * - ask for cleanup of dir on exit
- * - remove code-duplication with saveByteArrayToFile
- */
-void Attachments::slotOpenFile() {
-
- // TODO: make attachmentdir constant or configurable
- QString attachmentDir = qApp->applicationDirPath() + "/attachments/";
- //QDir p = QDir(qApp->applicationDirPath() + "/attachments/");
- if (!QDir(attachmentDir).exists()) {
- QDir().mkpath(attachmentDir);
- }
-
- QModelIndexList indexes = tableView->selectionModel()->selection().indexes();
- MimePart mp = table->getMimePart(indexes.at(0).row());
-
-// qDebug() << "mime: " << mp.header.getValue("Content-Type");
-
- QString filename = mp.header.getParam("Content-Type", "name");
- // TODO: find out why filename is quoted
-// qDebug() << "file: " << filename;
- filename.chop(1);
- filename.remove(0, 1);
- filename.prepend(attachmentDir);
-
- // qDebug() << "file: " << filename;
- QByteArray outBuffer = QByteArray::fromBase64(mp.body);
-
-
- QFile outfile(filename);
- if (!outfile.open(QFile::WriteOnly)) {
- QMessageBox::warning(this, tr("File"),
- tr("Cannot write file %1:\n%2.")
- .arg(filename)
- .arg(outfile.errorString()));
- return;
- }
-
- QDataStream out(&outfile);
- out.writeRawData(outBuffer.data(), outBuffer.length());
- outfile.close();
- QDesktopServices::openUrl(QUrl("file://" + filename, QUrl::TolerantMode));
-}
-
-void Attachments::addMimePart(MimePart *mp) {
- table->add(*mp);
-}
-
diff --git a/src/ui/widgets/EditorPage.cpp b/src/ui/widgets/EditorPage.cpp
index 8a51b721..05d5cbea 100644
--- a/src/ui/widgets/EditorPage.cpp
+++ b/src/ui/widgets/EditorPage.cpp
@@ -42,6 +42,9 @@ EditorPage::EditorPage(QString filePath, QWidget *parent) : QWidget(parent),
setAttribute(Qt::WA_DeleteOnClose);
textPage->setFocus();
+ // Front in same width
+ this->setFont({"Courier"});
+
connect(textPage, SIGNAL(textChanged()), this, SLOT(formatGpgHeader()));
}
diff --git a/src/ui/widgets/FilePage.cpp b/src/ui/widgets/FilePage.cpp
index bab6cf68..b9602d58 100644
--- a/src/ui/widgets/FilePage.cpp
+++ b/src/ui/widgets/FilePage.cpp
@@ -46,15 +46,33 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
createPopupMenu();
- upLevelButton = new QPushButton("Up");
+
+ upLevelButton = new QPushButton();
connect(upLevelButton, SIGNAL(clicked(bool)), this, SLOT(slotUpLevel()));
+ QString buttonStyle = "QPushButton{border:none;background-color:rgba(255, 255, 255,100);}";
+
+
+ auto upPixmap = QPixmap(":up.png");
+ upPixmap = upPixmap.scaled(18, 18, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ QIcon upButtonIcon(upPixmap);
+ upLevelButton->setIcon(upButtonIcon);
+ upLevelButton->setIconSize(upPixmap.rect().size());
+ upLevelButton->setStyleSheet(buttonStyle);
+
refreshButton = new QPushButton("Refresh");
connect(refreshButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath()));
- goPathButton = new QPushButton("Go");
+ goPathButton = new QPushButton();
connect(goPathButton, SIGNAL(clicked(bool)), this, SLOT(slotGoPath()));
+ auto updatePixmap = QPixmap(":refresh.png");
+ updatePixmap = updatePixmap.scaled(18, 18, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ QIcon updateButtonIcon(updatePixmap);
+ goPathButton->setIcon(updateButtonIcon);
+ goPathButton->setIconSize(updatePixmap.rect().size());
+ goPathButton->setStyleSheet(buttonStyle);
+
pathEdit = new QLineEdit();
pathEdit->setText(dirModel->rootPath());
@@ -62,7 +80,7 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
menuLayout->addWidget(upLevelButton);
menuLayout->setStretchFactor(upLevelButton, 1);
menuLayout->addWidget(pathEdit);
- menuLayout->setStretchFactor(pathEdit, 8);
+ menuLayout->setStretchFactor(pathEdit, 10);
menuLayout->addWidget(goPathButton);
menuLayout->setStretchFactor(goPathButton, 1);
// menuLayout->addWidget(refreshButton);
@@ -87,17 +105,22 @@ FilePage::FilePage(QWidget *parent) : QWidget(parent) {
}
void FilePage::fileTreeViewItemClicked(const QModelIndex &index) {
- mPath = dirModel->fileInfo(index).absoluteFilePath();
- qDebug() << "mPath" << mPath;
+ selectedPath = dirModel->fileInfo(index).absoluteFilePath();
+ qDebug() << "selectedPath" << selectedPath;
}
void FilePage::slotUpLevel() {
QModelIndex currentRoot = dirTreeView->rootIndex();
- mPath = dirModel->fileInfo(currentRoot.parent()).absoluteFilePath();
- auto fileInfo = QFileInfo(mPath);
+
+ mPath = dirModel->fileInfo(currentRoot).absoluteFilePath();
+ QDir dir(mPath);
+ dir.makeAbsolute();
+ dir.setPath(QDir::cleanPath(dir.filePath(QStringLiteral(".."))));
+ mPath = dir.absolutePath();
+ auto fileInfo = QFileInfo(dir.absolutePath());
if(fileInfo.isDir() && fileInfo.isReadable() && fileInfo.isExecutable()) {
- dirTreeView->setRootIndex(currentRoot.parent());
pathEdit->setText(mPath);
+ slotGoPath();
}
qDebug() << "Current Root mPath" << mPath;
emit pathChanged(mPath);
@@ -106,8 +129,9 @@ void FilePage::slotUpLevel() {
void FilePage::fileTreeViewItemDoubleClicked(const QModelIndex &index) {
mPath = dirModel->fileInfo(index).absoluteFilePath();
auto fileInfo = QFileInfo(mPath);
+ auto targetModelIndex = dirTreeView->model()->index(index.row(), 0, index.parent());
if(fileInfo.isDir() && fileInfo.isReadable() && fileInfo.isExecutable()) {
- dirTreeView->setRootIndex(index);
+ dirTreeView->setRootIndex(targetModelIndex);
pathEdit->setText(mPath);
}
qDebug() << "Index mPath" << mPath;
@@ -115,7 +139,7 @@ void FilePage::fileTreeViewItemDoubleClicked(const QModelIndex &index) {
}
QString FilePage::getSelected() const {
- return mPath;
+ return selectedPath;
}
void FilePage::slotGoPath() {
@@ -159,10 +183,10 @@ void FilePage::createPopupMenu() {
void FilePage::onCustomContextMenu(const QPoint &point) {
QModelIndex index = dirTreeView->indexAt(point);
- mPath = dirModel->fileInfo(index).absoluteFilePath();
- qDebug() << "Right Click" << mPath;
+ selectedPath = dirModel->fileInfo(index).absoluteFilePath();
+ qDebug() << "Right Click" << selectedPath;
if (index.isValid()) {
- QFileInfo info(mPath);
+ QFileInfo info(selectedPath);
encryptItemAct->setEnabled(info.isFile() && (info.suffix() != "gpg" && info.suffix() != "sig"));
decryptItemAct->setEnabled(info.isFile() && info.suffix() == "gpg");
signItemAct->setEnabled(info.isFile() && (info.suffix() != "gpg" && info.suffix() != "sig"));
@@ -234,3 +258,10 @@ void FilePage::slotVerifyItem() {
if(mainWindow != nullptr)
mainWindow->slotFileVerify();
}
+
+void FilePage::keyPressEvent(QKeyEvent *event) {
+ qDebug() << "Key Press" << event->key();
+ if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
+ slotGoPath();
+ }
+}
diff --git a/src/ui/widgets/InfoBoardWidget.cpp b/src/ui/widgets/InfoBoardWidget.cpp
index 33517a8e..f26917a4 100644
--- a/src/ui/widgets/InfoBoardWidget.cpp
+++ b/src/ui/widgets/InfoBoardWidget.cpp
@@ -25,7 +25,9 @@
#include "ui/widgets/InfoBoardWidget.h"
InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyList *keyList) :
- QWidget(parent), mCtx(ctx), mKeyList(keyList) {
+ QWidget(parent), mCtx(ctx), mKeyList(keyList), appPath(qApp->applicationDirPath()),
+ settings(RESOURCE_DIR(appPath) + "/conf/gpgfrontend.ini",
+ QSettings::IniFormat) {
infoBoard = new QTextEdit(this);
infoBoard->setReadOnly(true);
@@ -42,7 +44,7 @@ InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyLis
detailMenu->addAction(importFromKeyserverAct);
importFromKeyserverAct->setVisible(false);
- QWidget *actionButtonMenu = new QWidget();
+ auto *actionButtonMenu = new QWidget();
actionButtonMenu->setContentsMargins(0, 0, 0, 0);
actionButtonMenu->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
actionButtonMenu->setFixedHeight(36);
@@ -52,7 +54,7 @@ InfoBoardWidget::InfoBoardWidget(QWidget *parent, GpgME::GpgContext *ctx, KeyLis
actionButtonLayout->setSpacing(0);
actionButtonMenu->setLayout(actionButtonLayout);
- auto label = new QLabel("Optional Actions Menu");
+ auto label = new QLabel(tr("Optional Actions Menu"));
label->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
label->setContentsMargins(0, 0, 0, 0);
@@ -107,7 +109,8 @@ void InfoBoardWidget::setInfoBoard(const QString &text, InfoBoardStatus verifyLa
QPalette status = infoBoard->palette();
status.setColor(QPalette::Text, color);
infoBoard->setPalette(status);
- infoBoard->setFont(QFont("Times", 10));
+ auto infoBoardFontSize = settings.value("informationBoard/fontSize", 10).toInt();
+ infoBoard->setFont(QFont("Times", infoBoardFontSize));
}
void InfoBoardWidget::slotRefresh(const QString &text, InfoBoardStatus status) {
@@ -135,13 +138,16 @@ void InfoBoardWidget::associateTabWidget(QTabWidget *tab) {
disconnect(mTextPage, SIGNAL(textChanged()), this, SLOT(slotReset()));
// if (mFileTreeView != nullptr)
// disconnect(mFileTreeView, &FilePage::pathChanged, this, &InfoBoardWidget::slotReset);
- if (mTabWidget != nullptr)
+ if (mTabWidget != nullptr) {
disconnect(mTabWidget, SIGNAL(tabBarClicked(int)), this, SLOT(slotReset()));
+ connect(mTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(slotReset()));
+ }
mTextPage = nullptr;
mFileTreeView = nullptr;
mTabWidget = tab;
connect(tab, SIGNAL(tabBarClicked(int)), this, SLOT(slotReset()));
+ connect(tab, SIGNAL(tabCloseRequested(int)), this, SLOT(slotReset()));
}
void InfoBoardWidget::addOptionalAction(const QString &name, const std::function<void()> &action) {
diff --git a/src/ui/widgets/KeyList.cpp b/src/ui/widgets/KeyList.cpp
index b044020a..3929868e 100644
--- a/src/ui/widgets/KeyList.cpp
+++ b/src/ui/widgets/KeyList.cpp
@@ -297,6 +297,11 @@ void KeyList::contextMenuEvent(QContextMenuEvent *event)
}
+void KeyList::addSeparator()
+{
+ popupMenu->addSeparator();
+}
+
void KeyList::addMenuAction(QAction *act)
{
popupMenu->addAction(act);
diff --git a/src/ui/widgets/TextEdit.cpp b/src/ui/widgets/TextEdit.cpp
index 26cc3834..eab0f799 100644
--- a/src/ui/widgets/TextEdit.cpp
+++ b/src/ui/widgets/TextEdit.cpp
@@ -37,9 +37,6 @@ TextEdit::TextEdit(QWidget *parent) : QWidget(parent) {
layout->setSpacing(0);
setLayout(layout);
- // Front in same width
- this->setFont({"Courier"});
-
connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
SLOT(removeTab(int)));
connect(this, &TextEdit::insertTargetTextPage, this,
@@ -73,7 +70,7 @@ void TextEdit::slotNewHelpTab(const QString &title, const QString &path) const {
void TextEdit::slotNewFileTab() const {
auto *page = new FilePage(qobject_cast<QWidget *>(parent()));
- tabWidget->addTab(page, "[File Browser]");
+ tabWidget->addTab(page, "[Browser]");
tabWidget->setCurrentIndex(tabWidget->count() - 1);
connect(page, SIGNAL(pathChanged(const QString &)), this,
SLOT(slotFilePagePathChanged(const QString &)));
@@ -132,6 +129,7 @@ void TextEdit::slotInsertTargetTextPage(const QString &pagePtr,
auto *taregtTextPage = qobject_cast<EditorPage *>(it.value());
if (taregtTextPage != nullptr) {
taregtTextPage->getTextPage()->insertPlainText(text);
+ taregtTextPage->getTextPage()->document()->setModified(false);
}
}
}
@@ -164,6 +162,7 @@ void TextEdit::slotReadTargetTextPageDone(const QString &pagePtr) {
tabWidget->setTabText(index,
strippedName(taregtTextPage->getFilePath()));
}
+ taregtTextPage->getTextPage()->document()->setModified(false);
connect(taregtTextPage->getTextPage()->document(),
SIGNAL(modificationChanged(bool)), this,
SLOT(slotShowModified()));
@@ -638,13 +637,13 @@ void TextEdit::slotFilePagePathChanged(const QString &path) {
int index = tabWidget->currentIndex();
QString mPath;
QFileInfo fileInfo(path);
- QString tPath = fileInfo.path();
+ QString tPath = fileInfo.absoluteFilePath();
if (path.size() > 18) {
mPath = tPath.mid(tPath.size() - 18, 18).prepend("...");
} else {
mPath = tPath;
}
- mPath.prepend("[File Browser] ");
+ mPath.prepend("[Browser] ");
mPath.append("/");
tabWidget->setTabText(index, mPath);
}