File indexing completed on 2024-04-21 09:41:35

0001 /*
0002     SPDX-FileCopyrightText: 2002 Jean-Baptiste Mardelle <bj@altern.org>
0003     SPDX-FileCopyrightText: 2007, 2008, 2009, 2010, 2011 Rolf Eike Beer <kde@opensource.sf-tec.de>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kgpgeditor.h"
0008 
0009 #include "detailedconsole.h"
0010 #include "selectsecretkey.h"
0011 #include "kgpgmd5widget.h"
0012 #include "kgpgsettings.h"
0013 #include "keyservers.h"
0014 #include "sourceselect.h"
0015 #include "kgpg.h"
0016 #include "keysmanager.h"
0017 #include "editor/kgpgtextedit.h"
0018 #include "transactions/kgpgdecrypt.h"
0019 #include "transactions/kgpgkeyservergettransaction.h"
0020 #include "transactions/kgpgsigntext.h"
0021 #include "transactions/kgpgverify.h"
0022 #include <kgpgexternalactions.h>
0023 
0024 #include <KActionCollection>
0025 #include <KConfigGroup>
0026 #include <KEncodingFileDialog>
0027 #include <KFind>
0028 #include <KFindDialog>
0029 #include <KIO/Job>
0030 #include <KIO/StoredTransferJob>
0031 #include <KIO/StatJob>
0032 #include <KIO/RenameDialog>
0033 #include <KJobWidgets>
0034 #include <KLocalizedString>
0035 #include <KMessageBox>
0036 #include <KRecentFilesAction>
0037 #include <KSharedConfig>
0038 #include <KStandardAction>
0039 #include <KToggleAction>
0040 #include <KToolBar>
0041 #include <KUrlRequester>
0042 
0043 #include <QAction>
0044 #include <QFileDialog>
0045 #include <QIcon>
0046 #include <QMenuBar>
0047 #include <QPainter>
0048 #include <QPrintDialog>
0049 #include <QPrinter>
0050 #include <QTextStream>
0051 #include <QVBoxLayout>
0052 #include <QWidget>
0053 #include <kmessagebox.h>
0054 #include <qstringconverter_base.h>
0055 
0056 using namespace Qt::Literals::StringLiterals;
0057 
0058 class KgpgView : public QWidget {
0059 public:
0060     KgpgView(QWidget *parent, KgpgTextEdit *editor, KToolBar *toolbar);
0061 };
0062 
0063 KgpgView::KgpgView(QWidget *parent, KgpgTextEdit *editor, KToolBar *toolbar)
0064     : QWidget(parent)
0065 {
0066     QVBoxLayout *vb = new QVBoxLayout(this);
0067     vb->setSpacing(3);
0068     vb->addWidget(editor);
0069     vb->addWidget(toolbar);
0070 
0071     setAcceptDrops(true);
0072 }
0073 
0074 KgpgEditor::KgpgEditor(KeysManager *parent, KGpgItemModel *model, Qt::WindowFlags f)
0075     : KXmlGuiWindow(nullptr, f),
0076     m_editor(new KgpgTextEdit(this, model, parent)),
0077     m_recentfiles(nullptr),
0078     m_find(nullptr),
0079     m_textchanged(false),
0080     m_emptytext(true),
0081     m_model(model),
0082     m_parent(parent)
0083 {
0084     // call inits to invoke all other construction parts
0085     initActions();
0086 
0087     connect(m_editor, &KgpgTextEdit::resetEncoding, this, &KgpgEditor::slotResetEncoding);
0088     KgpgView *kb = new KgpgView(this, m_editor, toolBar(QLatin1String( "gpgToolBar" )));
0089     setCentralWidget(kb);
0090     setCaption(i18n("Untitled"), false);
0091     m_editredo->setEnabled(false);
0092     m_editundo->setEnabled(false);
0093     m_editcopy->setEnabled(false);
0094     m_editcut->setEnabled(false);
0095 
0096     setObjectName( QLatin1String("editor" ));
0097     slotSetFont(KGpgSettings::font());
0098     setupGUI((ToolBar | Keys | StatusBar | Save | Create), QLatin1String( "kgpgeditor.rc" ));
0099     setAutoSaveSettings(QLatin1String( "Editor" ), true);
0100 
0101     connect(m_editor, &KgpgTextEdit::textChanged, this, &KgpgEditor::modified);
0102     connect(m_editor, &KgpgTextEdit::newText, this, &KgpgEditor::newText);
0103     connect(m_editor, &KgpgTextEdit::undoAvailable, this, &KgpgEditor::slotUndoAvailable);
0104     connect(m_editor, &KgpgTextEdit::redoAvailable, this, &KgpgEditor::slotRedoAvailable);
0105     connect(m_editor, &KgpgTextEdit::copyAvailable, this, &KgpgEditor::slotCopyAvailable);
0106 }
0107 
0108 KgpgEditor::~KgpgEditor()
0109 {
0110     disconnect(m_editor, &KgpgTextEdit::textChanged, this, &KgpgEditor::modified);
0111     m_recentfiles->saveEntries( KConfigGroup(KSharedConfig::openConfig(), u"Recent Files"_s ) );
0112 }
0113 
0114 void KgpgEditor::openDocumentFile(const QUrl &url, const QString &encoding)
0115 {
0116     auto downloadJob = KIO::storedGet(url);
0117     KJobWidgets::setWindow(downloadJob , this);
0118     downloadJob->exec();
0119     if(!downloadJob->error())
0120     {
0121         QTextStream t(downloadJob->data());
0122         auto enc = QStringConverter::encodingForName(encoding.toLatin1().constData());
0123         if (enc) {
0124             t.setEncoding(*enc);
0125         }
0126         m_editor->setPlainText(t.readAll());
0127         m_docname = url;
0128         m_textchanged = false;
0129         m_emptytext = false;
0130         setCaption(url.fileName(), false);
0131         m_recentfiles->addUrl(url);
0132     }
0133 }
0134 
0135 void KgpgEditor::openEncryptedDocumentFile(const QUrl &url)
0136 {
0137     m_editor->slotDroppedFile(url);
0138 }
0139 
0140 void KgpgEditor::slotSetFont(QFont myFont)
0141 {
0142     m_editor->setFont(myFont);
0143 }
0144 
0145 void KgpgEditor::closeWindow()
0146 {
0147     m_recentfiles->saveEntries( KConfigGroup(KSharedConfig::openConfig(), u"Recent Files"_s ) );
0148     close();
0149 }
0150 
0151 void KgpgEditor::saveOptions()
0152 {
0153     KGpgSettings::setFirstRun(false);
0154     KGpgSettings::self()->save();
0155 }
0156 
0157 void KgpgEditor::initActions()
0158 {
0159     KStandardAction::openNew(this, &KgpgEditor::slotFileNew, actionCollection());
0160     KStandardAction::open(this, &KgpgEditor::slotFileOpen, actionCollection());
0161     KStandardAction::save(this, &KgpgEditor::slotFileSave, actionCollection());
0162     KStandardAction::saveAs(this, &KgpgEditor::slotFileSaveAs, actionCollection());
0163     KStandardAction::close(this, &KgpgEditor::slotFileClose, actionCollection());
0164     KStandardAction::paste(this, &KgpgEditor::slotEditPaste, actionCollection());
0165     KStandardAction::print(this, &KgpgEditor::slotFilePrint, actionCollection());
0166     KStandardAction::selectAll(this, &KgpgEditor::slotSelectAll, actionCollection());
0167     KStandardAction::find(this, &KgpgEditor::slotFind, actionCollection());
0168     KStandardAction::findNext(this, &KgpgEditor::slotFindNext, actionCollection());
0169     KStandardAction::findPrev(this, &KgpgEditor::slotFindPrev, actionCollection());
0170     actionCollection()->addAction(KStandardAction::Preferences, QLatin1String( "options_configure" ),
0171                                   this, SLOT(slotOptions()));
0172 
0173     m_editundo = KStandardAction::undo(this, &KgpgEditor::slotundo, actionCollection());
0174     m_editredo = KStandardAction::redo(this, &KgpgEditor::slotredo, actionCollection());
0175     m_editcopy = KStandardAction::copy(this, &KgpgEditor::slotEditCopy, actionCollection());
0176     m_editcut  = KStandardAction::cut(this, &KgpgEditor::slotEditCut, actionCollection());
0177 
0178     m_recentfiles = KStandardAction::openRecent(this, SLOT(openDocumentFile(QUrl)), this);
0179     menuBar()->addAction(m_recentfiles);
0180 
0181     m_recentfiles->loadEntries( KConfigGroup(KSharedConfig::openConfig(), u"Recent Files"_s ) );
0182     m_recentfiles->setMaxItems(KGpgSettings::recentFiles());
0183 
0184     QAction *action = actionCollection()->addAction(QLatin1String("file_encrypt"), this, &KgpgEditor::slotFilePreEnc);
0185     action->setIcon(QIcon::fromTheme( QLatin1String( "document-encrypt" )));
0186     action->setText(i18n("&Encrypt File..."));
0187 
0188     action = actionCollection()->addAction(QLatin1String("file_decrypt"), this, &KgpgEditor::slotFilePreDec);
0189     action->setIcon(QIcon::fromTheme( QLatin1String( "document-decrypt" )));
0190     action->setText(i18n("&Decrypt File..."));
0191 
0192     action = actionCollection()->addAction(QLatin1String("key_manage"), this, &KgpgEditor::slotKeyManager);
0193     action->setIcon(QIcon::fromTheme( QLatin1String( "kgpg" )));
0194     action->setText(i18n("&Open Key Manager"));
0195 
0196     action = actionCollection()->addAction(QLatin1String("sign_generate"), this, &KgpgEditor::slotPreSignFile);
0197     action->setText(i18n("&Generate Signature..."));
0198     action->setIcon(QIcon::fromTheme( QLatin1String( "document-sign-key" )));
0199 
0200     action = actionCollection()->addAction(QLatin1String("sign_verify"), this, &KgpgEditor::slotPreVerifyFile);
0201     action->setText(i18n("&Verify Signature..."));
0202 
0203     action = actionCollection()->addAction(QLatin1String("sign_check"), this, &KgpgEditor::slotCheckMd5);
0204     action->setText(i18n("&Check MD5 Sum..."));
0205 
0206     m_encodingaction = actionCollection()->add<KToggleAction>(QLatin1String("charsets"), this, &KgpgEditor::slotSetCharset);
0207     m_encodingaction->setText(i18n("&Unicode (utf-8) Encoding"));
0208 
0209     actionCollection()->addAction(m_recentfiles->objectName(), m_recentfiles);
0210 
0211     action = actionCollection()->addAction(QLatin1String("text_encrypt"), m_editor, &KgpgTextEdit::slotEncode);
0212     action->setIcon(QIcon::fromTheme( QLatin1String( "document-encrypt" )));
0213     action->setText(i18n("En&crypt"));
0214 
0215     action = actionCollection()->addAction(QLatin1String("text_decrypt"), m_editor, &KgpgTextEdit::slotDecode);
0216     action->setIcon(QIcon::fromTheme( QLatin1String( "document-decrypt" )));
0217     action->setText(i18n("&Decrypt"));
0218 
0219     action = actionCollection()->addAction(QLatin1String("text_sign_verify"), m_editor, &KgpgTextEdit::slotSignVerify);
0220     action->setIcon(QIcon::fromTheme( QLatin1String( "document-sign-key" )));
0221     action->setText(i18n("S&ign/Verify"));
0222 }
0223 
0224 bool KgpgEditor::queryClose()
0225 {
0226     bool b = saveBeforeClear();
0227     if (b) {
0228         m_editor->clear();
0229         newText();
0230     }
0231     return b;
0232 }
0233 
0234 bool KgpgEditor::saveBeforeClear()
0235 {
0236     if (m_textchanged)
0237     {
0238         QString fname;
0239         if (m_docname.fileName().isEmpty())
0240             fname = i18n("Untitled");
0241         else
0242             fname = m_docname.fileName();
0243 
0244         QString msg = i18n("The document \"%1\" has changed.\nDo you want to save it?", fname);
0245         QString caption = i18n("Close the document");
0246         int res = KMessageBox::warningTwoActionsCancel(this, msg, caption, KStandardGuiItem::save(), KStandardGuiItem::discard());
0247         if (res == KMessageBox::PrimaryAction)
0248             return slotFileSave();
0249         else
0250         if (res == KMessageBox::SecondaryAction)
0251             return true;
0252         else
0253             return false;
0254     }
0255 
0256     return true;
0257 }
0258 
0259 void KgpgEditor::slotFileNew()
0260 {
0261     if (saveBeforeClear())
0262     {
0263         m_editor->clear();
0264         newText();
0265     }
0266 }
0267 
0268 void KgpgEditor::slotFileOpen()
0269 {
0270     if (saveBeforeClear())
0271     {
0272         KEncodingFileDialog::Result loadResult;
0273         loadResult = KEncodingFileDialog::getOpenUrlAndEncoding(QString(), QUrl(), QString(), this);
0274         QUrl url = loadResult.URLs.first();
0275         m_textencoding = loadResult.encoding;
0276 
0277         if(!url.isEmpty())
0278             openDocumentFile(url, m_textencoding);
0279     }
0280 }
0281 
0282 bool KgpgEditor::slotFileSave()
0283 {
0284     QString filn = m_docname.path();
0285     if (filn.isEmpty())
0286         return slotFileSaveAs();
0287 
0288     auto encoding = QStringConverter::encodingForName(m_textencoding.toUtf8().data());
0289 
0290     if (!encoding) {
0291         KMessageBox::error(this, i18n("The document could not been saved, as the selected codec is not supported."));
0292         return false;
0293     }
0294 
0295     if (m_docname.isLocalFile())
0296     {
0297         QFile f(filn);
0298         if (!f.open(QIODevice::WriteOnly))
0299         {
0300             KMessageBox::error(this, i18n("The document could not be saved, please check your permissions and disk space."));
0301             return false;
0302         }
0303 
0304         QTextStream t(&f);
0305         t.setEncoding(*encoding);
0306         t << m_editor->toPlainText();
0307         f.close();
0308     }
0309     else
0310     {
0311         auto fromUnicode = QStringEncoder(*encoding);
0312         auto uploadJob = KIO::storedPut(fromUnicode(m_editor->toPlainText()), m_docname, -1);
0313         KJobWidgets::setWindow(uploadJob , this);
0314         uploadJob->exec();
0315         if(uploadJob->error())
0316         {
0317             KMessageBox::error(this, i18n("The document could not be saved, please check your permissions and disk space."));
0318             return false;
0319         }
0320     }
0321 
0322     m_textchanged = false;
0323     m_emptytext = false;
0324     setCaption(m_docname.fileName(), false);
0325     return true;
0326 }
0327 
0328 bool KgpgEditor::slotFileSaveAs()
0329 {
0330     KEncodingFileDialog::Result saveResult;
0331     saveResult = KEncodingFileDialog::getSaveUrlAndEncoding(QString(), QUrl(), QString(), this);
0332     QUrl url;
0333 
0334     if (!saveResult.URLs.empty())
0335         url = saveResult.URLs.first();
0336 
0337     if(!url.isEmpty()) {
0338         const QString selectedEncoding = saveResult.encoding;
0339         if (url.isLocalFile()) {
0340             QFile f(url.path());
0341             if (f.exists()) {
0342                 const QString message = i18n("Overwrite existing file %1?", url.fileName());
0343                 int result = KMessageBox::warningContinueCancel(this, message, QString(), KStandardGuiItem::overwrite());
0344                 if (result == KMessageBox::Cancel)
0345                     return false;
0346             }
0347             f.close();
0348         } else {
0349             auto statJob = KIO::stat(url, KIO::StatJob::DestinationSide, {});
0350             KJobWidgets::setWindow(statJob, this);
0351             statJob->exec();
0352             if (!statJob->error()) {
0353                 const QString message = i18n("Overwrite existing file %1?", url.fileName());
0354                 int result = KMessageBox::warningContinueCancel(this, message, QString(), KStandardGuiItem::overwrite());
0355                 if (result == KMessageBox::Cancel)
0356                     return false;
0357                         }
0358         }
0359 
0360         m_docname = url;
0361         m_textencoding = selectedEncoding;
0362         slotFileSave();
0363         return true;
0364     }
0365 
0366     return false;
0367 }
0368 
0369 void KgpgEditor::slotFilePrint()
0370 {
0371     QPrinter prt;
0372     QPointer<QPrintDialog> printDialog = new QPrintDialog(&prt, this);
0373     if (printDialog->exec() == QDialog::Accepted) {
0374         int width = prt.width();
0375         int height = prt.height();
0376         QPainter painter(&prt);
0377         painter.drawText(0, 0, width, height, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip, m_editor->toPlainText());
0378     }
0379     delete printDialog;
0380 }
0381 
0382 void KgpgEditor::slotFind()
0383 {
0384     QPointer<KFindDialog> fd = new KFindDialog(this);
0385 
0386     if (m_find) {
0387         fd->setOptions(m_find->options());
0388         fd->setPattern(m_find->pattern());
0389     }
0390 
0391     if (fd->exec() != QDialog::Accepted) {
0392         delete fd;
0393         return;
0394     }
0395 
0396     if (!m_find) {
0397         m_find = new KFind(fd->pattern(), fd->options(), this);
0398 
0399         if (m_find->options() & KFind::FromCursor)
0400             m_find->setData(m_editor->toPlainText(), m_editor->textCursor().selectionStart());
0401         else
0402             m_find->setData(m_editor->toPlainText());
0403         connect(m_find, &KFind::textFound, m_editor, &KgpgTextEdit::slotHighlightText);
0404         connect(m_find, &KFind::findNext, this, &KgpgEditor::slotFindText);
0405     } else {
0406         m_find->setPattern(fd->pattern());
0407         m_find->setOptions(fd->options());
0408         m_find->resetCounts();
0409     }
0410 
0411     slotFindText();
0412     delete fd;
0413 }
0414 
0415 void KgpgEditor::slotFindNext()
0416 {
0417     slotFindText();
0418 }
0419 
0420 void KgpgEditor::slotFindPrev()
0421 {
0422     if(!m_find)
0423     {
0424        slotFind();
0425        return;
0426     }
0427     long oldopt = m_find->options();
0428     long newopt = oldopt ^ KFind::FindBackwards;
0429     m_find->setOptions(newopt);
0430     slotFindText();
0431     if (m_find) {
0432         m_find->setOptions(oldopt);
0433     }
0434 }
0435 
0436 void KgpgEditor::slotFindText()
0437 {
0438     if (!m_find)
0439     {
0440         slotFind();
0441         return;
0442     }
0443 
0444     if (m_find->find() == KFind::NoMatch)
0445     {
0446         if (m_find->numMatches() == 0)
0447         {
0448             m_find->displayFinalDialog();
0449             delete m_find;
0450             m_find = nullptr;
0451         }
0452         else
0453         {
0454             if (m_find->shouldRestart(true, false))
0455             {
0456                 m_find->setData(m_editor->toPlainText());
0457                 slotFindText();
0458             }
0459             else
0460                 m_find->closeFindNextDialog();
0461         }
0462     }
0463 }
0464 
0465 void KgpgEditor::slotFilePreEnc()
0466 {
0467     QList<QUrl> urls = QFileDialog::getOpenFileUrls(this, i18n("Open File to Encode"), QUrl(), i18n("*|All Files"));
0468     if (urls.isEmpty())
0469         return;
0470 
0471     KGpgExternalActions::encryptFiles(m_parent, urls);
0472 }
0473 
0474 void KgpgEditor::slotFilePreDec()
0475 {
0476     QUrl url = QFileDialog::getOpenFileUrl(this, i18n("Open File to Decode"), QUrl(), i18n("*|All Files"));
0477     if (url.isEmpty())
0478         return;
0479 
0480     QString oldname = url.fileName();
0481     QString newname;
0482 
0483     if (oldname.endsWith(QLatin1String(".gpg")) || oldname.endsWith(QLatin1String(".asc")) || oldname.endsWith(QLatin1String(".pgp")))
0484         oldname.chop(4);
0485     else
0486         oldname.append(QLatin1String( ".clear" ));
0487     oldname.prepend(url.adjusted(QUrl::RemoveFilename).path());
0488 
0489     QPointer<QDialog> popn = new QDialog(this);
0490     popn->setWindowTitle(i18n("Decrypt File To"));
0491     QWidget *mainWidget = new QWidget(this);
0492     QVBoxLayout *mainLayout = new QVBoxLayout(popn);
0493     popn->setLayout(mainLayout);
0494     mainLayout->addWidget(mainWidget);
0495     popn->setModal( true );
0496 
0497     SrcSelect *page = new SrcSelect();
0498     mainLayout->addWidget(page);
0499     page->newFilename->setUrl(QUrl(oldname));
0500     page->newFilename->setMode(KFile::File);
0501     page->newFilename->setWindowTitle(i18n("Save File"));
0502 
0503     page->checkClipboard->setText(i18n("Editor"));
0504     page->resize(page->minimumSize());
0505     popn->resize(popn->minimumSize());
0506 
0507     page->buttonBox->button(QDialogButtonBox::Ok)->setShortcut(Qt::CTRL | Qt::Key_Return);
0508     connect(page->buttonBox, &QDialogButtonBox::accepted, popn.data(), &QDialog::accept);
0509     connect(page->buttonBox, &QDialogButtonBox::rejected, popn.data(), &QDialog::reject);
0510 
0511     if (popn->exec() == QDialog::Accepted)
0512     {
0513         if (page->checkFile->isChecked())
0514             newname = page->newFilename->url().path();
0515     }
0516     else
0517     {
0518         delete popn;
0519         return;
0520     }
0521     delete popn;
0522 
0523     if (!newname.isEmpty())
0524     {
0525         QFile fgpg(newname);
0526         if (fgpg.exists()) {
0527         QPointer<KIO::RenameDialog> over = new KIO::RenameDialog(this, i18n("File Already Exists"), QUrl(), QUrl::fromLocalFile(newname), KIO::RenameDialog_Overwrite);
0528 
0529         if (over->exec() != QDialog::Accepted) {
0530             delete over;
0531             return;
0532         }
0533         newname = over->newDestUrl().path();
0534         delete over;
0535         }
0536 
0537     KGpgDecrypt *decr = new KGpgDecrypt(this, url, QUrl(newname));
0538     connect(decr, &KGpgDecrypt::done, this, &KgpgEditor::slotLibraryDone);
0539     decr->start();
0540     }
0541     else
0542         openEncryptedDocumentFile(url);
0543 }
0544 
0545 void
0546 KgpgEditor::slotLibraryDone()
0547 {
0548     sender()->deleteLater();
0549 }
0550 
0551 void KgpgEditor::slotKeyManager()
0552 {
0553     m_parent->show();
0554     m_parent->raise();
0555 }
0556 
0557 void KgpgEditor::slotFileClose()
0558 {
0559     saveOptions();
0560     close();
0561 }
0562 
0563 void KgpgEditor::slotundo()
0564 {
0565     m_editor->undo();
0566 }
0567 
0568 void KgpgEditor::slotredo()
0569 {
0570     m_editor->redo();
0571 }
0572 
0573 void KgpgEditor::slotEditCut()
0574 {
0575     m_editor->cut();
0576 }
0577 
0578 void KgpgEditor::slotEditCopy()
0579 {
0580     m_editor->copy();
0581 }
0582 
0583 void KgpgEditor::slotEditPaste()
0584 {
0585     m_editor->paste();
0586 }
0587 
0588 void KgpgEditor::slotSelectAll()
0589 {
0590     m_editor->selectAll();
0591 }
0592 
0593 void KgpgEditor::slotSetCharset()
0594 {
0595     if (!m_encodingaction->isChecked())
0596         m_editor->setPlainText(QString::fromUtf8(m_editor->toPlainText().toLatin1()));
0597     else
0598     {
0599         m_editor->setPlainText(QLatin1String( m_editor->toPlainText().toUtf8() ));
0600     }
0601 }
0602 
0603 void KgpgEditor::slotResetEncoding(bool enc)
0604 {
0605     m_encodingaction->setChecked(enc);
0606 }
0607 
0608 void KgpgEditor::slotPreSignFile()
0609 {
0610     // create a detached signature for a chosen file
0611     QUrl url = QFileDialog::getOpenFileUrl(this, i18n("Open File to Sign"), QUrl(), i18n("*|All Files"));
0612     if (!url.isEmpty())
0613         slotSignFile(url);
0614 }
0615 
0616 void KgpgEditor::slotSignFile(const QUrl &url)
0617 {
0618     // create a detached signature for a chosen file
0619     if (!url.isEmpty())
0620     {
0621         QString signKeyID;
0622         QPointer<KgpgSelectSecretKey> opts = new KgpgSelectSecretKey(this, m_model, false);
0623         if (opts->exec() == QDialog::Accepted) {
0624             signKeyID = opts->getKeyID();
0625         } else {
0626             delete opts;
0627             return;
0628         }
0629 
0630         delete opts;
0631 
0632     KGpgSignText::SignOptions sopts = KGpgSignText::DetachedSignature;
0633     if (KGpgSettings::asciiArmor())
0634         sopts |= KGpgSignText::AsciiArmored;
0635 
0636     KGpgSignText *signt = new KGpgSignText(this, signKeyID, QList<QUrl>({url}), sopts);
0637     connect(signt, &KGpgSignText::done, this, &KgpgEditor::slotSignFileFin);
0638     signt->start();
0639     }
0640 }
0641 
0642 void KgpgEditor::slotSignFileFin(int)
0643 {
0644     sender()->deleteLater();
0645 }
0646 
0647 void KgpgEditor::slotPreVerifyFile()
0648 {
0649     QUrl url = QFileDialog::getOpenFileUrl(this, i18n("Open File to Verify"), QUrl(), i18n("*|All Files"));
0650     slotVerifyFile(url);
0651 }
0652 
0653 void KgpgEditor::slotVerifyFile(const QUrl &url)
0654 {
0655     if (url.isEmpty())
0656         return;
0657 
0658     QString sigfile;
0659     if (!url.fileName().endsWith(QLatin1String(".sig"))) {
0660         sigfile = url.path() + QLatin1String( ".sig" );
0661         if (!QFile::exists(sigfile)) {
0662             sigfile = url.path() + QLatin1String( ".asc" );
0663             // if no .asc or .sig signature file included, assume the file is internally signed
0664             if (!QFile::exists(sigfile))
0665                 sigfile.clear();
0666         }
0667     }
0668 
0669     QList<QUrl> chkfiles;
0670     if (sigfile.isEmpty())
0671         chkfiles << url;
0672     else
0673         chkfiles << QUrl::fromLocalFile(sigfile);
0674 
0675     KGpgVerify *verify = new KGpgVerify(this, chkfiles);
0676     connect(verify, &KGpgVerify::done, m_editor, &KgpgTextEdit::slotVerifyDone);
0677     verify->start();
0678 }
0679 
0680 void KgpgEditor::slotCheckMd5()
0681 {
0682     // display md5 sum for a chosen file
0683     QUrl url = QFileDialog::getOpenFileUrl(this, i18n("Open File to Verify"), QUrl(), i18n("*|All Files"));
0684     if (!url.isEmpty()) {
0685         QPointer<Md5Widget> mdwidget = new Md5Widget(this, url);
0686         mdwidget->exec();
0687         delete mdwidget;
0688     }
0689 }
0690 
0691 void KgpgEditor::importSignatureKey(const QString &id, const QString &fileName)
0692 {
0693     sender()->deleteLater();
0694 
0695         if (KMessageBox::questionTwoActions(nullptr,
0696             i18n("<qt><b>Missing signature:</b><br />Key id: %1<br /><br />Do you want to import this key from a keyserver?</qt>", id),
0697             fileName, KGuiItem(i18n("Import")), KGuiItem(i18n("Do Not Import"))) != KMessageBox::PrimaryAction)
0698         return;
0699 
0700     KeyServer *ks = new KeyServer(this);
0701 
0702     connect(ks, &KeyServer::importFinished, this, &KgpgEditor::slotDownloadKeysFinished);
0703     connect(ks, &KeyServer::importFailed, ks, &KeyServer::deleteLater);
0704 
0705     ks->startImport(QStringList(id), QString(),QLatin1String( qgetenv("http_proxy") ));
0706 }
0707 
0708 void KgpgEditor::slotDownloadKeysFinished(const QStringList &ids)
0709 {
0710     m_model->refreshKeys(ids);
0711 
0712     sender()->deleteLater();
0713 }
0714 
0715 void KgpgEditor::slotOptions()
0716 {
0717     m_parent->showOptions();
0718 }
0719 
0720 void KgpgEditor::modified()
0721 {
0722     QString capt = m_docname.fileName();
0723     if (m_emptytext) {
0724         m_textchanged = !m_editor->toPlainText().isEmpty();
0725         if (capt.isEmpty())
0726             capt = i18n("Untitled");
0727     } else {
0728         m_textchanged = true;
0729     }
0730     setCaption(capt, m_textchanged);
0731     m_editor->document()->setModified(m_textchanged);
0732 }
0733 
0734 void KgpgEditor::slotUndoAvailable(const bool v)
0735 {
0736     m_editundo->setEnabled(v);
0737 }
0738 
0739 void KgpgEditor::slotRedoAvailable(const bool v)
0740 {
0741     m_editredo->setEnabled(v);
0742 }
0743 
0744 void KgpgEditor::slotCopyAvailable(const bool v)
0745 {
0746     m_editcopy->setEnabled(v);
0747     m_editcut->setEnabled(v);
0748 }
0749 
0750 void KgpgEditor::newText()
0751 {
0752     m_textchanged = false;
0753     m_emptytext = true;
0754     m_docname.clear();
0755     setCaption(i18n("Untitled"), false);
0756     slotResetEncoding(false);
0757 }