00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "mainwindow.h"
00025 #include "tabbedbrowser.h"
00026 #include "helpdialog.h"
00027 #include "config.h"
00028
00029 #include <QDockWidget>
00030 #include <QDir>
00031 #include <QTimer>
00032 #include <QStatusBar>
00033 #include <QShortcut>
00034 #include <QMessageBox>
00035 #include <QPainter>
00036 #include <QEventLoop>
00037 #include <QtEvents>
00038 #include <QFontDatabase>
00039 #include <QWhatsThis>
00040 #include <QTextDocumentFragment>
00041 #include <QLibraryInfo>
00042 #include <QPrinter>
00043 #include <QPrintDialog>
00044 #include <QAbstractTextDocumentLayout>
00045 #include <QTextDocument>
00046 #include <QTextObject>
00047 #include <QFileDialog>
00048
00049 QList<MainWindow*> MainWindow::windows;
00050
00051 #if defined(Q_WS_WIN)
00052 extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
00053 #endif
00054
00055 MainWindow::MainWindow()
00056 {
00057 ui.setupUi(this);
00058
00059 #if defined(Q_WS_WIN)
00060
00061
00062 qt_ntfs_permission_lookup = 0;
00063 #endif
00064 setupCompleted = false;
00065
00066 goActions = QList<QAction*>();
00067 goActionDocFiles = new QMap<QAction*,QString>;
00068
00069 windows.append(this);
00070 tabs = new TabbedBrowser(this);
00071 setCentralWidget(tabs);
00072
00073 Config *config = Config::configuration();
00074
00075 updateProfileSettings();
00076
00077 dw = new QDockWidget(this);
00078 dw->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
00079 dw->setWindowTitle(tr("Sidebar"));
00080 dw->setObjectName(QLatin1String("sidebar"));
00081 helpDock = new HelpDialog(dw, this);
00082 dw->setWidget(helpDock);
00083
00084 addDockWidget(Qt::LeftDockWidgetArea, dw);
00085
00086
00087 setupGoActions();
00088
00089 restoreGeometry(config->windowGeometry());
00090 restoreState(config->mainWindowState());
00091 if (config->sideBarHidden())
00092 dw->hide();
00093
00094 tabs->setup();
00095 QTimer::singleShot(0, this, SLOT(setup()));
00096 #if defined(Q_WS_MAC)
00097 QMenu *windowMenu = new QMenu(tr("&Window"), this);
00098 menuBar()->insertMenu(ui.helpMenu->menuAction(), windowMenu);
00099 windowMenu->addAction(tr("Minimize"), this,
00100 SLOT(showMinimized()), QKeySequence(tr("Ctrl+M")));
00101
00102
00103
00104 ui.actionGoPrevious->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Left));
00105 ui.actionGoNext->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Right));
00106
00107 static const QLatin1String MacIconPath(":/trolltech/assistant/images/mac");
00108 ui.actionGoNext->setIcon(QIcon(MacIconPath + QLatin1String("/next.png")));
00109 ui.actionGoPrevious->setIcon(QIcon(MacIconPath + QLatin1String("/prev.png")));
00110 ui.actionGoHome->setIcon(QIcon(MacIconPath + QLatin1String("/home.png")));
00111 ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png")));
00112 ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png")));
00113 ui.actionEditFind->setIcon(QIcon(MacIconPath + QLatin1String("/find.png")));
00114 ui.actionFilePrint->setIcon(QIcon(MacIconPath + QLatin1String("/print.png")));
00115 ui.actionZoomOut->setIcon(QIcon(MacIconPath + QLatin1String("/zoomout.png")));
00116 ui.actionZoomIn->setIcon(QIcon(MacIconPath + QLatin1String("/zoomin.png")));
00117 ui.actionSyncToc->setIcon(QIcon(MacIconPath + QLatin1String("/synctoc.png")));
00118 ui.actionHelpWhatsThis->setIcon(QIcon(MacIconPath + QLatin1String("/whatsthis.png")));
00119 #endif
00120 }
00121
00122 MainWindow::~MainWindow()
00123 {
00124 windows.removeAll(this);
00125 delete goActionDocFiles;
00126 }
00127
00128 void MainWindow::setup()
00129 {
00130 if(setupCompleted)
00131 return;
00132
00133 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
00134 statusBar()->showMessage(tr("Initializing Qt Assistant..."));
00135 setupCompleted = true;
00136 helpDock->initialize();
00137 connect(ui.actionGoPrevious, SIGNAL(triggered()), tabs, SLOT(backward()));
00138 connect(ui.actionGoNext, SIGNAL(triggered()), tabs, SLOT(forward()));
00139 connect(ui.actionEditCopy, SIGNAL(triggered()), tabs, SLOT(copy()));
00140 connect(ui.actionFileExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
00141 connect(ui.actionAddBookmark, SIGNAL(triggered()),
00142 helpDock, SLOT(addBookmark()));
00143 connect(helpDock, SIGNAL(showLink(QString)),
00144 this, SLOT(showLink(QString)));
00145 connect(helpDock, SIGNAL(showSearchLink(QString,QStringList)),
00146 this, SLOT(showSearchLink(QString,QStringList)));
00147
00148 connect(ui.bookmarkMenu, SIGNAL(triggered(QAction*)),
00149 this, SLOT(showBookmark(QAction*)));
00150 connect(ui.actionZoomIn, SIGNAL(triggered()), tabs, SLOT(zoomIn()));
00151 connect(ui.actionZoomOut, SIGNAL(triggered()), tabs, SLOT(zoomOut()));
00152
00153 connect(ui.actionOpenPage, SIGNAL(triggered()), tabs, SLOT(newTab()));
00154 connect(ui.actionClosePage, SIGNAL(triggered()), tabs, SLOT(closeTab()));
00155 connect(ui.actionNextPage, SIGNAL(triggered()), tabs, SLOT(nextTab()));
00156 connect(ui.actionPrevPage, SIGNAL(triggered()), tabs, SLOT(previousTab()));
00157
00158
00159 #if defined(Q_OS_WIN32) || defined(Q_OS_WIN64)
00160 QShortcut *acc = new QShortcut(tr("SHIFT+CTRL+="), this);
00161 connect(acc, SIGNAL(activated()), ui.actionZoomIn, SIGNAL(triggered()));
00162 #endif
00163
00164 connect(new QShortcut(tr("Ctrl+T"), this), SIGNAL(activated()), helpDock, SLOT(toggleContents()));
00165 connect(new QShortcut(tr("Ctrl+I"), this), SIGNAL(activated()), helpDock, SLOT(toggleIndex()));
00166 connect(new QShortcut(tr("Ctrl+B"), this), SIGNAL(activated()), helpDock, SLOT(toggleBookmarks()));
00167 connect(new QShortcut(tr("Ctrl+S"), this), SIGNAL(activated()), helpDock, SLOT(toggleSearch()));
00168 connect(new QShortcut(tr("Ctrl+W"), this), SIGNAL(activated()), tabs, SLOT(closeTab()));
00169 connect(new QShortcut(tr("Ctrl+]"), this), SIGNAL(activated()), tabs, SLOT(nextTab()));
00170 connect(new QShortcut(tr("Ctrl+["), this), SIGNAL(activated()), tabs, SLOT(previousTab()));
00171
00172 Config *config = Config::configuration();
00173
00174 setupBookmarkMenu();
00175
00176 QAction *viewsAction = createPopupMenu()->menuAction();
00177 viewsAction->setText(tr("Views"));
00178 ui.viewMenu->addAction(viewsAction);
00179
00180 const int tabIndex = config->sideBarPage();
00181 helpDock->tabWidget()->setCurrentIndex(tabIndex);
00182
00183
00184 if (tabIndex == 0)
00185 helpDock->currentTabChanged(tabIndex);
00186 QObject::connect(ui.actionEditFind, SIGNAL(triggered()), tabs, SLOT(find()));
00187 QObject::connect(ui.actionEditFindNext, SIGNAL(triggered()), tabs, SLOT(findNext()));
00188 QObject::connect(ui.actionEditFindPrev, SIGNAL(triggered()), tabs, SLOT(findPrevious()));
00189 qApp->restoreOverrideCursor();
00190 ui.actionGoPrevious->setEnabled(false);
00191 ui.actionGoNext->setEnabled(false);
00192 }
00193
00194 void MainWindow::browserTabChanged()
00195 {
00196 if (tabs->currentBrowser()) {
00197 ui.actionGoPrevious->setEnabled(tabs->currentBrowser()->isBackwardAvailable());
00198 ui.actionGoNext->setEnabled(tabs->currentBrowser()->isForwardAvailable());
00199 }
00200 }
00201
00202 void MainWindow::setupGoActions()
00203 {
00204 Config *config = Config::configuration();
00205 QStringList titles = config->docTitles();
00206 QAction *action = 0;
00207
00208 static bool separatorInserted = false;
00209
00210 foreach (QAction *a, goActions) {
00211 ui.goMenu->removeAction(a);
00212 ui.goActionToolbar->removeAction(a);
00213 }
00214 qDeleteAll(goActions);
00215 goActions.clear();
00216 goActionDocFiles->clear();
00217
00218 int addCount = 0;
00219
00220 foreach (QString title, titles) {
00221 QPixmap pix = config->docIcon(title);
00222 if(!pix.isNull()) {
00223 if(!separatorInserted) {
00224 ui.goMenu->addSeparator();
00225 separatorInserted = true;
00226 }
00227 action = new QAction(this);
00228 action->setText(title);
00229 action->setWhatsThis(tr("Displays the main page of a specific documentation set."));
00230 action->setIcon(QIcon(pix));
00231 ui.goMenu->addAction(action);
00232 ui.goActionToolbar->addAction(action);
00233 goActions.append(action);
00234 goActionDocFiles->insert(action, config->indexPage(title));
00235 connect(action, SIGNAL(triggered()),
00236 this, SLOT(showGoActionLink()));
00237 ++addCount;
00238 }
00239 }
00240 if(!addCount)
00241 ui.goActionToolbar->hide();
00242 else
00243 ui.goActionToolbar->show();
00244
00245 }
00246
00247 bool MainWindow::insertActionSeparator()
00248 {
00249 ui.goMenu->addSeparator();
00250 ui.Toolbar->addSeparator();
00251 return true;
00252 }
00253
00254 void MainWindow::closeEvent(QCloseEvent *e)
00255 {
00256 saveSettings();
00257 e->accept();
00258 }
00259
00260 void MainWindow::about()
00261 {
00262 QMessageBox box(this);
00263 #if QT_EDITION == QT_EDITION_OPENSOURCE
00264 QString edition = tr("Open Source Edition");
00265 QString info = tr("This version of Qt Assistant is part of the Qt Open Source Edition, for use "
00266 "in the development of Open Source applications. "
00267 "Qt is a comprehensive C++ framework for cross-platform application "
00268 "development.");
00269 QString moreInfo = tr("You need a commercial Qt license for development of proprietary (closed "
00270 "source) applications. Please see <a href=\"http://www.trolltech.com/company/model"
00271 ".html\">www.trolltech.com/company/model.html</a> for an overview of Qt licensing.");
00272 #else
00273 QString edition;
00274 QString info;
00275 QString moreInfo(tr("This program is licensed to you under the terms of the "
00276 "Qt Commercial License Agreement. For details, see the file LICENSE "
00277 "that came with this software distribution."));
00278
00279 #endif
00280
00281 box.setText(QString("<center><img src=\":/trolltech/assistant/images/assistant-128.png\">"
00282 "<h3>%1</h3>"
00283 "<p>Version %2 %3</p></center>"
00284 "<p>%4</p>"
00285 "<p>%5</p>"
00286 "<p>Copyright (C) 2000-2006 Trolltech ASA. All rights reserved.</p>"
00287 "<p>The program is provided AS IS with NO WARRANTY OF ANY KIND,"
00288 " INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A"
00289 " PARTICULAR PURPOSE.<p/>")
00290 .arg(tr("Qt Assistant")).arg(QT_VERSION_STR).arg(edition).arg(info).arg(moreInfo));
00291 box.setWindowTitle(tr("Qt Assistant"));
00292 box.setIcon(QMessageBox::NoIcon);
00293 box.exec();
00294 }
00295
00296 void MainWindow::on_actionAboutApplication_triggered()
00297 {
00298 QString url = Config::configuration()->aboutURL();
00299 if (url == QLatin1String("about_qt")) {
00300 QMessageBox::aboutQt(this, QLatin1String("Qt Assistant"));
00301 return;
00302 }
00303 QString text;
00304 if (url.startsWith("file:"))
00305 url = url.mid(5);
00306 QFile file(url);
00307 if(file.exists() && file.open(QFile::ReadOnly))
00308 text = QString::fromUtf8(file.readAll());
00309 if(text.isNull())
00310 text = tr("Failed to open about application contents in file: '%1'").arg(url);
00311
00312 QMessageBox box(this);
00313 box.setText(text);
00314 box.setWindowTitle(Config::configuration()->aboutApplicationMenuText());
00315 box.setIcon(QMessageBox::NoIcon);
00316 box.exec();
00317 }
00318
00319 void MainWindow::on_actionAboutAssistant_triggered()
00320 {
00321 about();
00322 }
00323
00324 void MainWindow::on_actionGoHome_triggered()
00325 {
00326 QString home = MainWindow::urlifyFileName(Config::configuration()->homePage());
00327 showLink(home);
00328 }
00329
00330 QString MainWindow::urlifyFileName(const QString &fileName)
00331 {
00332 QString name = fileName;
00333 QUrl url(name);
00334
00335 #if defined(Q_OS_WIN32)
00336 if (!url.isValid() || url.scheme().isEmpty() || url.scheme().toLower() != "file:") {
00337 int i = name.indexOf('#');
00338 QString anchor = name.mid(i);
00339 name = name.toLower();
00340 if (i > -1)
00341 name.replace(i, anchor.length(), anchor);
00342 name.replace('\\', '/');
00343 foreach (QFileInfo drive, QDir::drives()) {
00344 if (name.startsWith(drive.absolutePath().toLower())) {
00345 name = "file:" + name;
00346 break;
00347 }
00348 }
00349 }
00350 #else
00351 if (!url.isValid() || url.scheme().isEmpty())
00352 name.prepend("file:");
00353 #endif
00354 return name;
00355 }
00356
00357 void MainWindow::on_actionFilePrint_triggered()
00358 {
00359 QPrinter printer(QPrinter::HighResolution);
00360 printer.setFullPage(true);
00361
00362 QPrintDialog *dlg = new QPrintDialog(&printer, this);
00363
00364 if (dlg->exec() == QDialog::Accepted) {
00365 tabs->currentBrowser()->document()->print(&printer);
00366 }
00367
00368 delete dlg;
00369 }
00370
00371 void MainWindow::updateBookmarkMenu()
00372 {
00373 for(QList<MainWindow*>::Iterator it = windows.begin(); it != windows.end(); ++it)
00374 (*it)->setupBookmarkMenu();
00375 }
00376
00377 void MainWindow::setupBookmarkMenu()
00378 {
00379 ui.bookmarkMenu->clear();
00380 bookmarks.clear();
00381 ui.bookmarkMenu->addAction(ui.actionAddBookmark);
00382
00383 QFile f(QDir::homePath() + QLatin1String("/.assistant/bookmarks.") +
00384 Config::configuration()->profileName());
00385 if (!f.open(QFile::ReadOnly))
00386 return;
00387 QTextStream ts(&f);
00388 ui.bookmarkMenu->addSeparator();
00389 while (!ts.atEnd()) {
00390 QString title = ts.readLine();
00391 QString link = ts.readLine();
00392 bookmarks.insert(ui.bookmarkMenu->addAction(title), link);
00393 }
00394 }
00395
00396 void MainWindow::showBookmark(QAction *action)
00397 {
00398 if (bookmarks.contains(action))
00399 showLink(bookmarks.value(action));
00400 }
00401
00402 void MainWindow::showLinkFromClient(const QString &link)
00403 {
00404 setWindowState(windowState() & ~Qt::WindowMinimized);
00405 raise();
00406 activateWindow();
00407 QString l = MainWindow::urlifyFileName(link);
00408 showLink(l);
00409 if (isMinimized())
00410 showNormal();
00411 }
00412
00413 void MainWindow::showLink(const QString &link)
00414 {
00415 if(link.isEmpty()) {
00416 qWarning("The link is empty!");
00417 }
00418
00419 QUrl url(link);
00420 QFileInfo fi(url.toLocalFile());
00421 tabs->setSource(url.toString());
00422 tabs->currentBrowser()->setFocus();
00423 }
00424
00425 void MainWindow::showLinks(const QStringList &links)
00426 {
00427 if (links.size() == 0) {
00428 qWarning("MainWindow::showLinks() - Empty link");
00429 return;
00430 }
00431
00432 if (links.size() == 1) {
00433 showLink(MainWindow::urlifyFileName(links.first()));
00434 return;
00435 }
00436
00437 QStringList::ConstIterator it = links.begin();
00438
00439 if (!tabs->currentBrowser()->source().isValid()) {
00440 QPair<HelpWindow*, QString> browser;
00441 browser.first = tabs->currentBrowser();
00442 browser.second = links.first();
00443 pendingBrowsers.append(browser);
00444 tabs->setTitle(tabs->currentBrowser(), tr("..."));
00445 }
00446 ++it;
00447
00448 while(it != links.end()) {
00449 QPair<HelpWindow*, QString> browser;
00450 browser.first = tabs->newBackgroundTab();
00451 browser.second = *it;
00452 pendingBrowsers.append(browser);
00453 ++it;
00454 }
00455
00456 startTimer(50);
00457 return;
00458 }
00459
00460 void MainWindow::removePendingBrowser(HelpWindow *win)
00461 {
00462 if (!pendingBrowsers.count())
00463 return;
00464
00465 QMutableListIterator<QPair<HelpWindow*, QString> > it(pendingBrowsers);
00466 while (it.hasNext()) {
00467 QPair<HelpWindow*, QString> browser = it.next();
00468 if (browser.first == win) {
00469 it.remove();
00470 break;
00471 }
00472 }
00473 }
00474
00475 void MainWindow::timerEvent(QTimerEvent *e)
00476 {
00477 QPair<HelpWindow*, QString> browser = pendingBrowsers.first();
00478 pendingBrowsers.pop_front();
00479
00480 if (pendingBrowsers.size() == 0)
00481 killTimer(e->timerId());
00482
00483 browser.first->setSource(MainWindow::urlifyFileName(browser.second));
00484 }
00485
00486 void MainWindow::showQtHelp()
00487 {
00488 showLink(QLibraryInfo::location(QLibraryInfo::DocumentationPath) +
00489 QLatin1String("/html/index.html"));
00490 }
00491
00492 MainWindow* MainWindow::newWindow()
00493 {
00494 saveSettings();
00495 MainWindow *mw = new MainWindow;
00496 mw->move(geometry().topLeft());
00497 if (isMaximized())
00498 mw->showMaximized();
00499 else
00500 mw->show();
00501 mw->on_actionGoHome_triggered();
00502 return mw;
00503 }
00504
00505 void MainWindow::saveSettings()
00506 {
00507 Config *config = Config::configuration();
00508
00509 config->setSideBarPage(helpDock->tabWidget()->currentIndex());
00510 config->setWindowGeometry(saveGeometry());
00511 config->setMainWindowState(saveState());
00512
00513
00514 QStringList lst;
00515 QList<HelpWindow*> browsers = tabs->browsers();
00516 foreach (HelpWindow *browser, browsers)
00517 lst << browser->source().toString();
00518 config->setSource(lst);
00519 config->save();
00520 }
00521
00522 TabbedBrowser* MainWindow::browsers() const
00523 {
00524 return tabs;
00525 }
00526
00527 void MainWindow::showSearchLink(const QString &link, const QStringList &terms)
00528 {
00529 HelpWindow * hw = tabs->currentBrowser();
00530 hw->blockScrolling(true);
00531 hw->setCursor(Qt::WaitCursor);
00532 if (hw->source() == link)
00533 hw->reload();
00534 else
00535 showLink(link);
00536 hw->setCursor(Qt::ArrowCursor);
00537
00538 hw->viewport()->setUpdatesEnabled(false);
00539
00540 QTextCharFormat marker;
00541 marker.setForeground(Qt::red);
00542
00543 QTextCursor firstHit;
00544
00545 QTextCursor c = hw->textCursor();
00546 c.beginEditBlock();
00547 foreach (QString term, terms) {
00548 c.movePosition(QTextCursor::Start);
00549 hw->setTextCursor(c);
00550
00551 bool found = hw->find(term, QTextDocument::FindWholeWords);
00552 while (found) {
00553 QTextCursor hit = hw->textCursor();
00554 if (firstHit.isNull() || hit.position() < firstHit.position())
00555 firstHit = hit;
00556
00557 hit.mergeCharFormat(marker);
00558 found = hw->find(term, QTextDocument::FindWholeWords);
00559 }
00560 }
00561
00562 if (firstHit.isNull()) {
00563 firstHit = hw->textCursor();
00564 firstHit.movePosition(QTextCursor::Start);
00565 }
00566 firstHit.clearSelection();
00567 c.endEditBlock();
00568 hw->setTextCursor(firstHit);
00569
00570 hw->blockScrolling(false);
00571 hw->viewport()->setUpdatesEnabled(true);
00572 }
00573
00574
00575 void MainWindow::showGoActionLink()
00576 {
00577 const QObject *origin = sender();
00578 if(!origin ||
00579 QLatin1String(origin->metaObject()->className()) != QLatin1String("QAction"))
00580 return;
00581
00582 QAction *action = (QAction*) origin;
00583 QString docfile = *(goActionDocFiles->find(action));
00584 showLink(MainWindow::urlifyFileName(docfile));
00585 }
00586
00587 void MainWindow::on_actionHelpAssistant_triggered()
00588 {
00589 showLink(Config::configuration()->assistantDocPath() + QLatin1String("/assistant-manual.html"));
00590 }
00591
00592 HelpDialog* MainWindow::helpDialog() const
00593 {
00594 return helpDock;
00595 }
00596
00597 void MainWindow::backwardAvailable(bool enable)
00598 {
00599 ui.actionGoPrevious->setEnabled(enable);
00600 }
00601
00602 void MainWindow::forwardAvailable(bool enable)
00603 {
00604 ui.actionGoNext->setEnabled(enable);
00605 }
00606
00607 void MainWindow::updateProfileSettings()
00608 {
00609 Config *config = Config::configuration();
00610 #ifndef Q_WS_MAC
00611 setWindowIcon(config->applicationIcon());
00612 #endif
00613 ui.helpMenu->clear();
00614
00615
00616 ui.helpMenu->addAction(ui.actionAboutAssistant);
00617 if (!config->aboutApplicationMenuText().isEmpty())
00618 ui.helpMenu->addAction(ui.actionAboutApplication);
00619 ui.helpMenu->addSeparator();
00620 ui.helpMenu->addAction(ui.actionHelpWhatsThis);
00621
00622 ui.actionAboutApplication->setText(config->aboutApplicationMenuText());
00623
00624 if(!config->title().isNull())
00625 setWindowTitle(config->title());
00626 }
00627
00628 void MainWindow::setupPopupMenu(QMenu *m)
00629 {
00630 m->addAction(ui.actionNewWindow);
00631 m->addAction(ui.actionOpenPage);
00632 m->addAction(ui.actionClosePage);
00633 m->addSeparator();
00634 m->addAction(ui.actionSaveAs);
00635 m->addSeparator();
00636 m->addAction(ui.actionGoPrevious);
00637 m->addAction(ui.actionGoNext);
00638 m->addAction(ui.actionGoHome);
00639 m->addSeparator();
00640 m->addAction(ui.actionZoomIn);
00641 m->addAction(ui.actionZoomOut);
00642 m->addSeparator();
00643 m->addAction(ui.actionEditCopy);
00644 m->addAction(ui.actionEditFind);
00645 }
00646
00647 void MainWindow::on_actionSyncToc_triggered()
00648 {
00649 HelpWindow *w = tabs->currentBrowser();
00650 if(w) {
00651 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
00652 QString link = w->source().toString();
00653 helpDock->locateContents(link);
00654 qApp->restoreOverrideCursor();
00655 }
00656 }
00657
00658 void MainWindow::on_actionNewWindow_triggered()
00659 {
00660 newWindow()->show();
00661 }
00662
00663 void MainWindow::on_actionClose_triggered()
00664 {
00665 close();
00666 }
00667
00668 void MainWindow::on_actionHelpWhatsThis_triggered()
00669 {
00670 QWhatsThis::enterWhatsThisMode();
00671 }
00672
00673 void MainWindow::on_actionSaveAs_triggered()
00674 {
00675 QString fileName;
00676 QUrl url = tabs->currentBrowser()->source();
00677 if (url.isValid()) {
00678 QFileInfo fi(url.toLocalFile());
00679 fileName = fi.fileName();
00680 }
00681 fileName = QFileDialog::getSaveFileName(this, tr("Save Page"), fileName);
00682 if (fileName.isEmpty())
00683 return;
00684
00685 QFile file(fileName);
00686 if (!file.open(QIODevice::WriteOnly)) {
00687 QMessageBox::critical(this, tr("Save Page"), tr("Cannot open file for writing!"));
00688 return;
00689 }
00690
00691 QFileInfo fi(fileName);
00692 QString fn = fi.fileName();
00693 int i = fn.lastIndexOf('.');
00694 if (i > -1)
00695 fn = fn.left(i);
00696 QString relativeDestPath = fn + "_images";
00697 QDir destDir(fi.absolutePath() + QDir::separator() + relativeDestPath);
00698 bool imgDirAvailable = destDir.exists();
00699 if (!imgDirAvailable)
00700 imgDirAvailable = destDir.mkdir(destDir.absolutePath());
00701
00702
00703 QTextDocument *doc = tabs->currentBrowser()->document()->clone();
00704 if (url.isValid() && imgDirAvailable) {
00705 QTextBlock::iterator it;
00706 for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) {
00707 for (it = block.begin(); !(it.atEnd()); ++it) {
00708 QTextFragment fragment = it.fragment();
00709 if (fragment.isValid()) {
00710 QTextImageFormat fm = fragment.charFormat().toImageFormat();
00711 if (fm.isValid() && !fm.name().isEmpty()) {
00712 QUrl imagePath = tabs->currentBrowser()->source().resolved(fm.name());
00713 if (!imagePath.isValid())
00714 continue;
00715 QString from = imagePath.toLocalFile();
00716 QString destName = fm.name();
00717 int j = destName.lastIndexOf('/');
00718 if (j > -1)
00719 destName = destName.mid(j+1);
00720 QFileInfo info(from);
00721 if (info.exists()) {
00722 if (!QFile::copy(from, destDir.absolutePath()
00723 + QDir::separator() + destName))
00724 continue;
00725 fm.setName("./" + relativeDestPath + "/" + destName);
00726 QTextCursor cursor(doc);
00727 cursor.setPosition(fragment.position());
00728 cursor.setPosition(fragment.position() + fragment.length(),
00729 QTextCursor::KeepAnchor);
00730 cursor.setCharFormat(fm);
00731 }
00732 }
00733 }
00734 }
00735 }
00736 }
00737 QString src = doc->toHtml("utf-8");
00738 QTextStream s(&file);
00739 s.setCodec("utf-8");
00740 s << src;
00741 s.flush();
00742 file.close();
00743 }