00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "kgpgeditor.h"
00019
00020 #include <QTextStream>
00021 #include <QTextCodec>
00022 #include <QPainter>
00023 #include <QtDBus/QtDBus>
00024 #include <QtGui/QPrinter>
00025 #include <QtGui/QPrintDialog>
00026
00027 #include <KToggleAction>
00028 #include <KStandardAction>
00029 #include <KActionCollection>
00030 #include <KIcon>
00031 #include <KFindDialog>
00032 #include <KFind>
00033 #include <KShortcut>
00034 #include <KEncodingFileDialog>
00035 #include <kio/netaccess.h>
00036 #include <kio/renamedialog.h>
00037 #include <KMessageBox>
00038 #include <KTemporaryFile>
00039 #include <KAction>
00040 #include <KLocale>
00041 #include <KDebug>
00042
00043 #include "selectsecretkey.h"
00044 #include "kgpgmd5widget.h"
00045 #include "kgpgsettings.h"
00046 #include "kgpglibrary.h"
00047 #include "keyservers.h"
00048 #include "sourceselect.h"
00049 #include "kgpgview.h"
00050 #include "kgpg.h"
00051 #include "kgpg_interface.h"
00052 #include "kgpgtextinterface.h"
00053
00054
00055 KgpgEditor::KgpgEditor(QWidget *parent, KGpgItemModel *model, Qt::WFlags f, KShortcut gohome, bool mainwindow)
00056 : KXmlGuiWindow(parent, f), view(new KgpgView(this, model))
00057 {
00058 m_ismainwindow = mainwindow;
00059 m_godefaultkey = gohome;
00060 m_find = 0;
00061 m_model = model;
00062
00063 setAttribute(Qt::WA_DeleteOnClose, false);
00064
00065 initActions();
00066
00067 connect(view, SIGNAL(resetEncoding(bool)), this, SLOT(slotResetEncoding(bool)));
00068 setCentralWidget(view);
00069 setCaption(i18n("Untitled"), false);
00070 m_editredo->setEnabled(false);
00071 m_editundo->setEnabled(false);
00072 m_editcopy->setEnabled(false);
00073 m_editcut->setEnabled(false);
00074 m_textchanged = false;
00075
00076 setObjectName("editor");
00077 slotSetFont(KGpgSettings::font());
00078 setupGUI((ToolBar | Keys | StatusBar | Save | Create), "kgpg.rc");
00079 setAutoSaveSettings("Editor", true);
00080
00081 connect(view, SIGNAL(textChanged()), this, SLOT(modified()));
00082 connect(view, SIGNAL(newText()), this, SLOT(newText()));
00083 connect(view->editor, SIGNAL(undoAvailable(bool)), this, SLOT(slotUndoAvailable(bool)));
00084 connect(view->editor, SIGNAL(redoAvailable(bool)), this, SLOT(slotRedoAvailable(bool)));
00085 connect(view->editor, SIGNAL(copyAvailable(bool)), this, SLOT(slotCopyAvailable(bool)));
00086 }
00087
00088 KgpgEditor::~KgpgEditor()
00089 {
00090 delete view;
00091 }
00092
00093 void KgpgEditor::openDocumentFile(const KUrl& url, const QString &encoding)
00094 {
00095 QString tempopenfile;
00096 if(KIO::NetAccess::download(url, tempopenfile, this))
00097 {
00098 QFile qfile(tempopenfile);
00099 if (qfile.open(QIODevice::ReadOnly))
00100 {
00101 QTextStream t(&qfile);
00102 t.setCodec(encoding.toAscii());
00103 view->editor->setPlainText(t.readAll());
00104 qfile.close();
00105 m_docname = url;
00106 m_textchanged = false;
00107 setCaption(url.fileName(), false);
00108 }
00109 KIO::NetAccess::removeTempFile(tempopenfile);
00110 }
00111 }
00112
00113 void KgpgEditor::openEncryptedDocumentFile(const KUrl& url)
00114 {
00115 view->editor->slotDroppedFile(url);
00116 }
00117
00118 void KgpgEditor::slotSetFont(QFont myFont)
00119 {
00120 view->editor->setFont(myFont);
00121 }
00122
00123 void KgpgEditor::closeWindow()
00124 {
00125 close();
00126 }
00127
00128 void KgpgEditor::saveOptions()
00129 {
00130 KGpgSettings::setFirstRun(false);
00131 KGpgSettings::self()->writeConfig();
00132 }
00133
00134 void KgpgEditor::initActions()
00135 {
00136 KStandardAction::openNew(this, SLOT(slotFileNew()), actionCollection());
00137 KStandardAction::open(this, SLOT(slotFileOpen()), actionCollection());
00138 KStandardAction::save(this, SLOT(slotFileSave()), actionCollection());
00139 KStandardAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
00140 KStandardAction::close(this, SLOT(slotFileClose()), actionCollection());
00141 KStandardAction::paste(this, SLOT(slotEditPaste()), actionCollection());
00142 KStandardAction::print(this, SLOT(slotFilePrint()), actionCollection());
00143 KStandardAction::selectAll(this, SLOT(slotSelectAll()), actionCollection());
00144 KStandardAction::find(this, SLOT(slotFind()), actionCollection());
00145 KStandardAction::findNext(this, SLOT(slotFindNext()), actionCollection());
00146 KStandardAction::findPrev(this, SLOT(slotFindPrev()), actionCollection());
00147 actionCollection()->addAction(KStandardAction::Preferences, "kgpg_config",
00148 this, SLOT(slotOptions()));
00149
00150 m_editundo = KStandardAction::undo(this, SLOT(slotundo()), actionCollection());
00151 m_editredo = KStandardAction::redo(this, SLOT(slotredo()), actionCollection());
00152 m_editcopy = KStandardAction::copy(this, SLOT(slotEditCopy()), actionCollection());
00153 m_editcut = KStandardAction::cut(this, SLOT(slotEditCut()), actionCollection());
00154
00155 QAction *action = actionCollection()->addAction("file_encrypt");
00156 action->setIcon(KIcon("document-encrypt"));
00157 action->setText(i18n("&Encrypt File..."));
00158 connect(action, SIGNAL(triggered(bool)), SLOT(slotFilePreEnc()));
00159 action = actionCollection()->addAction("file_decrypt");
00160 action->setIcon(KIcon("document-decrypt"));
00161 action->setText(i18n("&Decrypt File..."));
00162 connect(action, SIGNAL(triggered(bool)), SLOT(slotFilePreDec()));
00163 action = actionCollection()->addAction("key_manage");
00164 action->setIcon(KIcon("kgpg"));
00165 action->setText(i18n("&Open Key Manager"));
00166 connect(action, SIGNAL(triggered(bool)), SLOT(slotKeyManager()));
00167 action = actionCollection()->addAction("sign_generate");
00168 action->setText(i18n("&Generate Signature..."));
00169 connect(action, SIGNAL(triggered(bool) ), SLOT(slotPreSignFile()));
00170 action = actionCollection()->addAction("sign_verify");
00171 action->setText(i18n("&Verify Signature..."));
00172 connect(action, SIGNAL(triggered(bool) ), SLOT(slotPreVerifyFile()));
00173 action = actionCollection()->addAction("sign_check");
00174 action->setText(i18n("&Check MD5 Sum..."));
00175 connect(action, SIGNAL(triggered(bool) ), SLOT(slotCheckMd5()));
00176
00177 m_encodingaction = actionCollection()->add<KToggleAction>("charsets");
00178 m_encodingaction->setText(i18n("&Unicode (utf-8) Encoding"));
00179 connect(m_encodingaction, SIGNAL(triggered(bool) ), SLOT(slotSetCharset()));
00180 }
00181
00182 bool KgpgEditor::queryClose()
00183 {
00184 return saveBeforeClear();
00185 }
00186
00187 bool KgpgEditor::saveBeforeClear()
00188 {
00189 if (m_textchanged)
00190 {
00191 QString fname;
00192 if (m_docname.fileName().isEmpty())
00193 fname = i18n("Untitled");
00194 else
00195 fname = m_docname.fileName();
00196
00197 QString msg = i18n("The document \"%1\" has changed.\nDo you want to save it?", fname);
00198 QString caption = i18n("Close the document");
00199 int res = KMessageBox::warningYesNoCancel(this, msg, caption, KStandardGuiItem::save(), KStandardGuiItem::discard());
00200 if (res == KMessageBox::Yes)
00201 return slotFileSave();
00202 else
00203 if (res == KMessageBox::No)
00204 return true;
00205 else
00206 return false;
00207 }
00208
00209 return true;
00210 }
00211
00212 void KgpgEditor::slotFileNew()
00213 {
00214 if (saveBeforeClear())
00215 {
00216 view->editor->clear();
00217 newText();
00218 }
00219 }
00220
00221 void KgpgEditor::slotFileOpen()
00222 {
00223 if (saveBeforeClear())
00224 {
00225 KEncodingFileDialog::Result loadResult;
00226 loadResult = KEncodingFileDialog::getOpenUrlAndEncoding(QString(), QString(), QString(), this);
00227 KUrl url = loadResult.URLs.first();
00228 m_textencoding = loadResult.encoding;
00229
00230 if(!url.isEmpty())
00231 openDocumentFile(url, m_textencoding);
00232 }
00233 }
00234
00235 bool KgpgEditor::slotFileSave()
00236 {
00237 QString filn = m_docname.path();
00238 if (filn.isEmpty())
00239 return slotFileSaveAs();
00240
00241 QTextCodec *cod = QTextCodec::codecForName(m_textencoding.toAscii());
00242
00243 if (!checkEncoding(cod))
00244 {
00245 KMessageBox::sorry(this, i18n("The document could not been saved, as the selected encoding cannot encode every unicode character in it."));
00246 return false;
00247 }
00248
00249 if (m_docname.isLocalFile())
00250 {
00251 QFile f(filn);
00252 if (!f.open(QIODevice::WriteOnly))
00253 {
00254 KMessageBox::sorry(this, i18n("The document could not be saved, please check your permissions and disk space."));
00255 return false;
00256 }
00257
00258 QTextStream t(&f);
00259 t.setCodec(cod);
00260 t << view->editor->toPlainText();
00261 f.close();
00262 }
00263 else
00264 {
00265 KTemporaryFile tmpfile;
00266 tmpfile.open();
00267 QTextStream stream(&tmpfile);
00268 stream.setCodec(cod);
00269 stream << view->editor->toPlainText();
00270
00271 if(!KIO::NetAccess::upload(tmpfile.fileName(), m_docname, this))
00272 {
00273 KMessageBox::sorry(this, i18n("The document could not be saved, please check your permissions and disk space."));
00274 return false;
00275 }
00276 }
00277
00278 m_textchanged = false;
00279 setCaption(m_docname.fileName(), false);
00280 return true;
00281 }
00282
00283 bool KgpgEditor::slotFileSaveAs()
00284 {
00285 KEncodingFileDialog::Result saveResult;
00286 saveResult = KEncodingFileDialog::getSaveUrlAndEncoding(QString(), QString(), QString(), this);
00287 KUrl url = saveResult.URLs.first();
00288 QString selectedEncoding = saveResult.encoding;
00289
00290 if(!url.isEmpty())
00291 {
00292 if (url.isLocalFile())
00293 {
00294 QString filn = url.path();
00295 QFile f(filn);
00296 if (f.exists())
00297 {
00298 QString message = i18n("Overwrite existing file %1?", url.fileName());
00299 int result = KMessageBox::warningContinueCancel(this, QString(message), QString(), KStandardGuiItem::overwrite());
00300 if (result == KMessageBox::Cancel)
00301 return false;
00302 }
00303 f.close();
00304 }
00305 else
00306 if (KIO::NetAccess::exists(url, KIO::NetAccess::DestinationSide, this))
00307 {
00308 QString message = i18n("Overwrite existing file %1?", url.fileName());
00309 int result = KMessageBox::warningContinueCancel(this, QString(message), QString(), KStandardGuiItem::overwrite());
00310 if (result == KMessageBox::Cancel)
00311 return false;
00312 }
00313
00314 m_docname = url;
00315 m_textencoding = selectedEncoding;
00316 slotFileSave();
00317 return true;
00318 }
00319 return false;
00320 }
00321
00322 void KgpgEditor::slotFilePrint()
00323 {
00324 QPrinter prt;
00325 QPrintDialog printDialog(&prt, this);
00326 if (printDialog.exec())
00327 {
00328 int width = prt.width();
00329 int height = prt.height();
00330 QPainter painter(&prt);
00331 painter.drawText(0, 0, width, height, Qt::AlignLeft | Qt::AlignTop | Qt::TextDontClip, view->editor->toPlainText());
00332 }
00333 }
00334
00335 void KgpgEditor::slotFind()
00336 {
00337 KFindDialog fd(this);
00338
00339 if (m_find)
00340 {
00341 fd.setOptions(m_find->options());
00342 fd.setPattern(m_find->pattern());
00343 }
00344
00345 if (fd.exec() != QDialog::Accepted)
00346 return;
00347
00348 if (!m_find)
00349 {
00350 m_find = new KFind(fd.pattern(), fd.options(), this);
00351 if (m_find->options() & KFind::FromCursor)
00352 m_find->setData(view->editor->toPlainText(), view->editor->textCursor().selectionStart());
00353 else
00354 m_find->setData(view->editor->toPlainText());
00355 connect(m_find, SIGNAL(highlight(QString, int, int)), view, SLOT(slotHighlightText(QString, int, int)));
00356 connect(m_find, SIGNAL(findNext()), this, SLOT(slotFindText()));
00357 }
00358 else
00359 {
00360 m_find->setPattern(fd.pattern());
00361 m_find->setOptions(fd.options());
00362 m_find->resetCounts();
00363 }
00364
00365 slotFindText();
00366 }
00367
00368 void KgpgEditor::slotFindNext()
00369 {
00370 slotFindText();
00371 }
00372
00373 void KgpgEditor::slotFindPrev()
00374 {
00375 if(!m_find)
00376 {
00377 slotFind();
00378 return;
00379 }
00380 long oldopt = m_find->options();
00381 long newopt = oldopt ^ KFind::FindBackwards;
00382 m_find->setOptions(newopt);
00383 slotFindText();
00384 m_find->setOptions(oldopt);
00385 }
00386
00387 void KgpgEditor::slotFindText()
00388 {
00389 if (!m_find)
00390 {
00391 slotFind();
00392 return;
00393 }
00394
00395 if (m_find->find() == KFind::NoMatch)
00396 {
00397 if (m_find->numMatches() == 0)
00398 {
00399 m_find->displayFinalDialog();
00400 delete m_find;
00401 m_find = 0;
00402 }
00403 else
00404 {
00405 if (m_find->shouldRestart(true, false))
00406 {
00407 m_find->setData(view->editor->toPlainText());
00408 slotFindText();
00409 }
00410 else
00411 m_find->closeFindNextDialog();
00412 }
00413 }
00414 }
00415
00416 void KgpgEditor::slotFilePreEnc()
00417 {
00418 QStringList opts;
00419 KUrl::List urls = KFileDialog::getOpenUrls(KUrl(), i18n("*|All Files"), this, i18n("Open File to Encode"));
00420 if (urls.isEmpty())
00421 return;
00422 emit encryptFiles(urls);
00423 }
00424
00425 void KgpgEditor::slotFilePreDec()
00426 {
00427 KUrl url = KFileDialog::getOpenUrl(KUrl(), i18n("*|All Files"), this, i18n("Open File to Decode"));
00428 if (url.isEmpty())
00429 return;
00430
00431 QString oldname = url.fileName();
00432 QString newname;
00433
00434 if (oldname.endsWith(".gpg") || oldname.endsWith(".asc") || oldname.endsWith(".pgp"))
00435 oldname.truncate(oldname.length() - 4);
00436 else
00437 oldname.append(".clear");
00438 oldname.prepend(url.directory(KUrl::IgnoreTrailingSlash));
00439
00440 KDialog *popn = new KDialog(this );
00441 popn->setCaption( i18n("Decrypt File To") );
00442 popn->setButtons( KDialog::Ok | KDialog::Cancel );
00443 popn->setDefaultButton( KDialog::Ok );
00444 popn->setModal( true );
00445
00446 SrcSelect *page = new SrcSelect();
00447 popn->setMainWidget(page);
00448 page->newFilename->setUrl(oldname);
00449 page->newFilename->setMode(KFile::File);
00450 page->newFilename->setWindowTitle(i18n("Save File"));
00451
00452 page->checkClipboard->setText(i18n("Editor"));
00453 page->resize(page->minimumSize());
00454 popn->resize(popn->minimumSize());
00455 if (popn->exec() == QDialog::Accepted)
00456 {
00457 if (page->checkFile->isChecked())
00458 newname = page->newFilename->url().path();
00459 }
00460 else
00461 {
00462 delete popn;
00463 return;
00464 }
00465 delete popn;
00466
00467 if (!newname.isEmpty())
00468 {
00469 QFile fgpg(newname);
00470 if (fgpg.exists())
00471 {
00472 KIO::RenameDialog over(0, i18n("File Already Exists"), KUrl(), KUrl::fromPath(newname), KIO::M_OVERWRITE);
00473 if (over.exec() == QDialog::Rejected)
00474 {
00475 return;
00476 }
00477 newname = over.newDestUrl().path();
00478 }
00479
00480 KgpgLibrary *lib = new KgpgLibrary(this);
00481 lib->slotFileDec(url, KUrl(newname), m_customdecrypt);
00482 connect(lib, SIGNAL(importOver(KgpgLibrary *, QStringList)), SIGNAL(slotRefreshImported(KgpgLibrary *, QStringList)));
00483 }
00484 else
00485 openEncryptedDocumentFile(url);
00486 }
00487
00488 void
00489 KgpgEditor::slotRefreshImported(KgpgLibrary *lib, const QStringList &keys)
00490 {
00491 lib->deleteLater();
00492 emit refreshImported(keys);
00493 }
00494
00495 void KgpgEditor::slotKeyManager()
00496 {
00497 OrgKdeKgpgKeyInterface kgpg("org.kde.kgpg", "/KeyInterface",QDBusConnection::sessionBus());
00498 QDBusReply<void> reply =kgpg.showKeyManager();
00499 if (!reply.isValid())
00500 kDebug(2100) << "there was some error using dbus." ;
00501 }
00502
00503 void KgpgEditor::slotFileClose()
00504 {
00505 saveOptions();
00506 close();
00507 }
00508
00509 void KgpgEditor::slotundo()
00510 {
00511 view->editor->undo();
00512 }
00513
00514 void KgpgEditor::slotredo()
00515 {
00516 view->editor->redo();
00517 }
00518
00519 void KgpgEditor::slotEditCut()
00520 {
00521 view->editor->cut();
00522 }
00523
00524 void KgpgEditor::slotEditCopy()
00525 {
00526 view->editor->copy();
00527 }
00528
00529 void KgpgEditor::slotEditPaste()
00530 {
00531 view->editor->paste();
00532 }
00533
00534 void KgpgEditor::slotSelectAll()
00535 {
00536 view->editor->selectAll();
00537 }
00538
00539 void KgpgEditor::slotSetCharset()
00540 {
00541 if (!m_encodingaction->isChecked())
00542 view->editor->setPlainText(QString::fromUtf8(view->editor->toPlainText().toAscii()));
00543 else
00544 {
00545 if (checkEncoding(QTextCodec::codecForLocale()))
00546 return;
00547 view->editor->setPlainText(view->editor->toPlainText().toUtf8());
00548 }
00549 }
00550
00551 bool KgpgEditor::checkEncoding(QTextCodec *codec)
00552 {
00553 return codec->canEncode(view->editor->toPlainText());
00554 }
00555
00556 void KgpgEditor::slotResetEncoding(bool enc)
00557 {
00558 m_encodingaction->setChecked(enc);
00559 }
00560
00561 void KgpgEditor::slotPreSignFile()
00562 {
00563
00564 KUrl url = KFileDialog::getOpenUrl(KUrl(), i18n("*|All Files"), this, i18n("Open File to Sign"));
00565 if (!url.isEmpty())
00566 slotSignFile(url);
00567 }
00568
00569 void KgpgEditor::slotSignFile(const KUrl &url)
00570 {
00571
00572 if (!url.isEmpty())
00573 {
00574 QString signKeyID;
00575 KgpgSelectSecretKey *opts = new KgpgSelectSecretKey(this, m_model, false);
00576 if (opts->exec() == QDialog::Accepted)
00577 signKeyID = opts->getKeyID();
00578 else
00579 {
00580 delete opts;
00581 return;
00582 }
00583
00584 delete opts;
00585
00586 QStringList Options;
00587 if (KGpgSettings::asciiArmor())
00588 Options << QString::fromLocal8Bit("--armor");
00589 if (KGpgSettings::pgpCompatibility())
00590 Options << QString::fromLocal8Bit("--pgp6");
00591
00592 KGpgTextInterface *interface = new KGpgTextInterface();
00593
00594 interface->signFiles(signKeyID, url, Options);
00595 }
00596 }
00597
00598 void KgpgEditor::slotSignFileFin(KgpgInterface *interface)
00599 {
00600 delete interface;
00601 }
00602
00603 void KgpgEditor::slotPreVerifyFile()
00604 {
00605 KUrl url = KFileDialog::getOpenUrl(KUrl(), i18n("*|All Files"), this, i18n("Open File to Verify"));
00606 slotVerifyFile(url);
00607 }
00608
00609 void KgpgEditor::slotVerifyFile(const KUrl &url)
00610 {
00611 if (!url.isEmpty())
00612 {
00613 QString sigfile;
00614 if (!url.fileName().endsWith(".sig"))
00615 {
00616 sigfile = url.path() + ".sig";
00617 QFile fsig(sigfile);
00618 if (!fsig.exists())
00619 {
00620 sigfile = url.path() + ".asc";
00621 QFile fsig(sigfile);
00622
00623 if (!fsig.exists())
00624 sigfile.clear();
00625 }
00626 }
00627
00628
00629 KGpgTextInterface *interface = new KGpgTextInterface();
00630 interface->KgpgVerifyFile(url, KUrl(sigfile));
00631 connect(interface, SIGNAL(verifyquerykey(QString)), this, SLOT(importSignatureKey(QString)));
00632 }
00633 }
00634
00635 void KgpgEditor::slotCheckMd5()
00636 {
00637
00638 KUrl url = KFileDialog::getOpenUrl(KUrl(), i18n("*|All Files"), this, i18n("Open File to Verify"));
00639 if (!url.isEmpty())
00640 {
00641 Md5Widget *mdwidget = new Md5Widget(this, url);
00642 mdwidget->exec();
00643 delete mdwidget;
00644 }
00645 }
00646
00647 void KgpgEditor::importSignatureKey(const QString &id)
00648 {
00649 KeyServer *kser = new KeyServer(0, false);
00650 kser->slotSetText(id);
00651 kser->slotImport();
00652 }
00653
00654 void KgpgEditor::slotOptions()
00655 {
00656 OrgKdeKgpgKeyInterface kgpg("org.kde.kgpg", "/KeyInterface",QDBusConnection::sessionBus());
00657 QDBusReply<void> reply =kgpg.showOptions();
00658 if (!reply.isValid())
00659 kDebug(2100) << "there was some error using dbus." ;
00660 }
00661
00662 void KgpgEditor::modified()
00663 {
00664 if (!m_textchanged)
00665 {
00666 QString capt = m_docname.fileName();
00667 if (capt.isEmpty())
00668 capt = i18n("Untitled");
00669 setCaption(capt, true);
00670 m_textchanged = true;
00671 }
00672 }
00673
00674 void KgpgEditor::slotUndoAvailable(const bool &v)
00675 {
00676 m_editundo->setEnabled(v);
00677 }
00678
00679 void KgpgEditor::slotRedoAvailable(const bool &v)
00680 {
00681 m_editredo->setEnabled(v);
00682 }
00683
00684 void KgpgEditor::slotCopyAvailable(const bool &v)
00685 {
00686 m_editcopy->setEnabled(v);
00687 m_editcut->setEnabled(v);
00688 }
00689
00690 void KgpgEditor::newText()
00691 {
00692 m_textchanged = false;
00693 m_docname.clear();
00694 setCaption(i18n("Untitled"), false);
00695 slotResetEncoding(false);
00696 }
00697
00698 #include "kgpgeditor.moc"