diff -r 000000000000 -r 1918ee327afb tools/assistant/compat/mainwindow.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/assistant/compat/mainwindow.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,885 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Assistant of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "tabbedbrowser.h" +#include "helpdialog.h" +#include "config.h" +#include "fontsettingsdialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +QList MainWindow::windows; + +#if defined(Q_WS_WIN) +extern Q_CORE_EXPORT int qt_ntfs_permission_lookup; +#endif + +MainWindow::MainWindow() +{ + setUnifiedTitleAndToolBarOnMac(true); + ui.setupUi(this); + +#if defined(Q_WS_WIN) + // Workaround for QMimeSourceFactory failing in QFileInfo::isReadable() for + // certain user configs. See task: 34372 + qt_ntfs_permission_lookup = 0; +#endif + setupCompleted = false; + + goActions = QList(); + goActionDocFiles = new QMap; + + windows.append(this); + tabs = new TabbedBrowser(this); + connect(tabs, SIGNAL(tabCountChanged(int)), this, SLOT(updateTabActions(int))); + setCentralWidget(tabs); + + Config *config = Config::configuration(); + + updateProfileSettings(); + + dw = new QDockWidget(this); + dw->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dw->setWindowTitle(tr("Sidebar")); + dw->setObjectName(QLatin1String("sidebar")); + helpDock = new HelpDialog(dw, this); + dw->setWidget(helpDock); + + addDockWidget(Qt::LeftDockWidgetArea, dw); + + // read geometry configuration + setupGoActions(); + + restoreGeometry(config->windowGeometry()); + restoreState(config->mainWindowState()); + if (config->sideBarHidden()) + dw->hide(); + + tabs->setup(); + QTimer::singleShot(0, this, SLOT(setup())); +#if defined(Q_WS_MAC) + QMenu *windowMenu = new QMenu(tr("&Window"), this); + menuBar()->insertMenu(ui.helpMenu->menuAction(), windowMenu); + windowMenu->addAction(tr("Minimize"), this, + SLOT(showMinimized()), QKeySequence(tr("Ctrl+M"))); + // Use the same forward and backward browser shortcuts as Safari and Internet Explorer do + // on the Mac. This means that if you have access to one of those cool Intellimice, the thing + // works just fine, since that's how Microsoft hacked it. + ui.actionGoPrevious->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Left)); + ui.actionGoNext->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Right)); + + static const QLatin1String MacIconPath(":/trolltech/assistant/images/mac"); + ui.actionGoNext->setIcon(QIcon(MacIconPath + QLatin1String("/next.png"))); + ui.actionGoPrevious->setIcon(QIcon(MacIconPath + QLatin1String("/prev.png"))); + ui.actionGoHome->setIcon(QIcon(MacIconPath + QLatin1String("/home.png"))); + ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png"))); + ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png"))); + ui.actionEditFind->setIcon(QIcon(MacIconPath + QLatin1String("/find.png"))); + ui.actionFilePrint->setIcon(QIcon(MacIconPath + QLatin1String("/print.png"))); + ui.actionZoomOut->setIcon(QIcon(MacIconPath + QLatin1String("/zoomout.png"))); + ui.actionZoomIn->setIcon(QIcon(MacIconPath + QLatin1String("/zoomin.png"))); + ui.actionSyncToc->setIcon(QIcon(MacIconPath + QLatin1String("/synctoc.png"))); + ui.actionHelpWhatsThis->setIcon(QIcon(MacIconPath + QLatin1String("/whatsthis.png"))); +#elif defined(Q_WS_X11) + ui.actionGoNext->setIcon(QIcon::fromTheme("go-next" , ui.actionGoNext->icon())); + ui.actionGoPrevious->setIcon(QIcon::fromTheme("go-previous" , ui.actionGoPrevious->icon())); + ui.actionGoHome->setIcon(QIcon::fromTheme("user-home" , ui.actionGoHome->icon())); + ui.actionEditCopy->setIcon(QIcon::fromTheme("edit-copy" , ui.actionEditCopy->icon())); + ui.actionEditFind->setIcon(QIcon::fromTheme("edit-find" , ui.actionEditFind->icon())); + ui.actionFilePrint->setIcon(QIcon::fromTheme("document-print" , ui.actionFilePrint->icon())); + ui.actionZoomOut->setIcon(QIcon::fromTheme("zoom-out" , ui.actionZoomOut->icon())); + ui.actionZoomIn->setIcon(QIcon::fromTheme("zoom-in" , ui.actionZoomIn->icon())); + ui.actionSyncToc->setIcon(QIcon::fromTheme("view-refresh" , ui.actionSyncToc->icon())); +#endif +} + +MainWindow::~MainWindow() +{ + windows.removeAll(this); + delete goActionDocFiles; +} + +void MainWindow::setup() +{ + if(setupCompleted) + return; + + qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); + statusBar()->showMessage(tr("Initializing Qt Assistant...")); + setupCompleted = true; + helpDock->initialize(); + connect(ui.actionGoPrevious, SIGNAL(triggered()), tabs, SLOT(backward())); + connect(ui.actionGoNext, SIGNAL(triggered()), tabs, SLOT(forward())); + connect(ui.actionEditCopy, SIGNAL(triggered()), tabs, SLOT(copy())); + connect(ui.actionFileExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows())); + connect(ui.actionAddBookmark, SIGNAL(triggered()), + helpDock, SLOT(addBookmark())); + connect(helpDock, SIGNAL(showLink(QString)), + this, SLOT(showLink(QString))); + connect(helpDock, SIGNAL(showSearchLink(QString,QStringList)), + this, SLOT(showSearchLink(QString,QStringList))); + + connect(ui.bookmarkMenu, SIGNAL(triggered(QAction*)), + this, SLOT(showBookmark(QAction*))); + connect(ui.actionZoomIn, SIGNAL(triggered()), tabs, SLOT(zoomIn())); + connect(ui.actionZoomOut, SIGNAL(triggered()), tabs, SLOT(zoomOut())); + + connect(ui.actionOpenPage, SIGNAL(triggered()), tabs, SLOT(newTab())); + connect(ui.actionClosePage, SIGNAL(triggered()), tabs, SLOT(closeTab())); + connect(ui.actionNextPage, SIGNAL(triggered()), tabs, SLOT(nextTab())); + connect(ui.actionPrevPage, SIGNAL(triggered()), tabs, SLOT(previousTab())); + + +#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) + QShortcut *acc = new QShortcut(tr("SHIFT+CTRL+="), this); + connect(acc, SIGNAL(activated()), ui.actionZoomIn, SIGNAL(triggered())); +#endif + + connect(new QShortcut(tr("Ctrl+T"), this), SIGNAL(activated()), helpDock, SLOT(toggleContents())); + connect(new QShortcut(tr("Ctrl+I"), this), SIGNAL(activated()), helpDock, SLOT(toggleIndex())); + connect(new QShortcut(tr("Ctrl+B"), this), SIGNAL(activated()), helpDock, SLOT(toggleBookmarks())); + connect(new QShortcut(tr("Ctrl+S"), this), SIGNAL(activated()), helpDock, SLOT(toggleSearch())); + connect(new QShortcut(tr("Ctrl+]"), this), SIGNAL(activated()), tabs, SLOT(nextTab())); + connect(new QShortcut(tr("Ctrl+["), this), SIGNAL(activated()), tabs, SLOT(previousTab())); + + Config *config = Config::configuration(); + + setupBookmarkMenu(); + + QAction *viewsAction = createPopupMenu()->menuAction(); + viewsAction->setText(tr("Views")); + ui.viewMenu->addAction(viewsAction); + + const int tabIndex = config->sideBarPage(); + helpDock->tabWidget()->setCurrentIndex(tabIndex); + // The tab index is 0 by default, so we need to force an upate + // to poulate the contents in this case. + if (tabIndex == 0) + helpDock->currentTabChanged(tabIndex); + + ui.actionEditFind->setShortcut(QKeySequence::Find); + ui.actionEditFindNext->setShortcut(QKeySequence::FindNext); + ui.actionEditFindPrev->setShortcut(QKeySequence::FindPrevious); + + QObject::connect(ui.actionEditFind, SIGNAL(triggered()), tabs, SLOT(find())); + QObject::connect(ui.actionEditFindNext, SIGNAL(triggered()), tabs, SLOT(findNext())); + QObject::connect(ui.actionEditFindPrev, SIGNAL(triggered()), tabs, SLOT(findPrevious())); + connect(ui.actionEditFont_Settings, SIGNAL(triggered()), this, SLOT(showFontSettingsDialog())); + + qApp->restoreOverrideCursor(); + ui.actionGoPrevious->setEnabled(false); + ui.actionGoNext->setEnabled(false); + ui.actionEditCopy->setEnabled(false); + + // set the current selected item in the treeview + helpDialog()->locateContents(tabs->currentBrowser()->source().toString()); + connect(tabs, SIGNAL(browserUrlChanged(QString)), helpDock, SLOT(locateContents(QString))); +} + +void MainWindow::browserTabChanged() +{ + HelpWindow *win = tabs->currentBrowser(); + if (win) { + QTextCursor cursor(win->textCursor()); + ui.actionEditCopy->setEnabled(cursor.hasSelection()); + ui.actionGoPrevious->setEnabled(win->isBackwardAvailable()); + ui.actionGoNext->setEnabled(win->isForwardAvailable()); + } +} + +void MainWindow::copyAvailable(bool yes) +{ + ui.actionEditCopy->setEnabled(yes); +} + +void MainWindow::updateTabActions(int index) +{ + bool enabled = (index > 1) ? true : false; + ui.actionPrevPage->setEnabled(enabled); + ui.actionNextPage->setEnabled(enabled); + ui.actionClosePage->setEnabled(enabled); +} + +void MainWindow::setupGoActions() +{ + Config *config = Config::configuration(); + QStringList titles = config->docTitles(); + QAction *action = 0; + + static bool separatorInserted = false; + + foreach (QAction *a, goActions) { + ui.goMenu->removeAction(a); + ui.goActionToolbar->removeAction(a); + } + qDeleteAll(goActions); + goActions.clear(); + goActionDocFiles->clear(); + + int addCount = 0; + + foreach (QString title, titles) { + QPixmap pix = config->docIcon(title); + if(!pix.isNull()) { + if(!separatorInserted) { + ui.goMenu->addSeparator(); + separatorInserted = true; + } + action = new QAction(this); + action->setText(title); + action->setWhatsThis(tr("Displays the main page of a specific documentation set.")); + action->setIcon(QIcon(pix)); + ui.goMenu->addAction(action); + ui.goActionToolbar->addAction(action); + goActions.append(action); + goActionDocFiles->insert(action, config->indexPage(title)); + connect(action, SIGNAL(triggered()), + this, SLOT(showGoActionLink())); + ++addCount; + } + } + if(!addCount) + ui.goActionToolbar->hide(); + else + ui.goActionToolbar->show(); + +} + +bool MainWindow::insertActionSeparator() +{ + ui.goMenu->addSeparator(); + ui.Toolbar->addSeparator(); + return true; +} + +void MainWindow::closeEvent(QCloseEvent *e) +{ + saveSettings(); + e->accept(); +} + +void MainWindow::about() +{ + QMessageBox box(this); + + box.setText(QString::fromLatin1("
" + "

%1

" + "

Version %2

" + "

Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

") + .arg(tr("Qt Assistant")).arg(QLatin1String(QT_VERSION_STR))); + box.setWindowTitle(tr("Qt Assistant")); + box.setIcon(QMessageBox::NoIcon); + box.exec(); +} + +void MainWindow::on_actionAboutApplication_triggered() +{ + QString url = Config::configuration()->aboutURL(); + if (url == QLatin1String("about_qt")) { + QMessageBox::aboutQt(this, QLatin1String("Qt Assistant")); + return; + } + QString text; + if (url.startsWith(QLatin1String("file:"))) + url = url.mid(5); + QFile file(url); + if(file.exists() && file.open(QFile::ReadOnly)) + text = QString::fromUtf8(file.readAll()); + if(text.isNull()) + text = tr("Failed to open about application contents in file: '%1'").arg(url); + + QFileInfo fi(file); + QString path = QDir::cleanPath(fi.absolutePath()); + if (!QDir::searchPaths(QLatin1String("aboutImages")).contains(path)) + QDir::addSearchPath(QLatin1String("aboutImages"), path); + + QMessageBox box(this); + box.setText(text); + box.setWindowTitle(Config::configuration()->aboutApplicationMenuText()); + box.setIcon(QMessageBox::NoIcon); + box.exec(); +} + +void MainWindow::on_actionAboutAssistant_triggered() +{ + about(); +} + +void MainWindow::on_actionGoHome_triggered() +{ + QString home = MainWindow::urlifyFileName(Config::configuration()->homePage()); + showLink(home); +} + +QString MainWindow::urlifyFileName(const QString &fileName) +{ + QString name = fileName; + QUrl url(name); + +#if defined(Q_OS_WIN32) + if (!url.isValid() || url.scheme().isEmpty() || url.scheme().toLower() != QLatin1String("file:")) { + int i = name.indexOf(QLatin1Char('#')); + QString anchor = name.mid(i); + name = name.toLower(); + if (i > -1) + name.replace(i, anchor.length(), anchor); + name.replace(QLatin1Char('\\'), QLatin1Char('/')); + foreach (QFileInfo drive, QDir::drives()) { + if (name.startsWith(drive.absolutePath().toLower())) { + name = QLatin1String("file:") + name; + break; + } + } + } +#else + if (!url.isValid() || url.scheme().isEmpty()) + name.prepend(QLatin1String("file:")); +#endif + return name; +} + +#ifndef QT_NO_PRINTER +class PrintThread : public QThread +{ + QPrinter _printer; + QTextDocument *_document; + +public: + PrintThread(QObject *parent) + : QThread(parent), _printer(QPrinter::HighResolution), _document(0) + { + } + ~PrintThread() + { + wait(); + } + + QPrinter *printer() + { + return &_printer; + } + + void start(QTextDocument *document) + { + _document = document->clone(); + _document->moveToThread(this); + QThread::start(); + } + +protected: + void run() + { + _document->print(printer()); + delete _document; + _document = 0; + } +}; +#endif //QT_NO_PRINTER + +void MainWindow::on_actionFilePrint_triggered() +{ +#ifndef QT_NO_PRINTER + if (!QFontDatabase::supportsThreadedFontRendering()) { + QPrinter printer(QPrinter::HighResolution); + + QPrintDialog dlg(&printer, this); + if (dlg.exec() == QDialog::Accepted) { + qApp->setOverrideCursor(Qt::WaitCursor); + tabs->currentBrowser()->document()->print(&printer); + qApp->restoreOverrideCursor(); + } + return; + } + + PrintThread *thread = new PrintThread(this); + + QPrintDialog dlg(thread->printer(), this); + if (dlg.exec() == QDialog::Accepted) { + connect(thread, SIGNAL(finished()), SLOT(printingFinished())); + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + + qApp->setOverrideCursor(Qt::BusyCursor); + thread->start(tabs->currentBrowser()->document()); + } else { + delete thread; + } +#else + Q_ASSERT("No printing support"); +#endif +} + +void MainWindow::printingFinished() +{ + qApp->restoreOverrideCursor(); +} + +void MainWindow::updateBookmarkMenu() +{ + for(QList::Iterator it = windows.begin(); it != windows.end(); ++it) + (*it)->setupBookmarkMenu(); +} + +void MainWindow::setupBookmarkMenu() +{ + ui.bookmarkMenu->clear(); + bookmarks.clear(); + ui.bookmarkMenu->addAction(ui.actionAddBookmark); + + QFile f(QDir::homePath() + QLatin1String("/.assistant/bookmarks.") + + Config::configuration()->profileName()); + if (!f.open(QFile::ReadOnly)) + return; + QTextStream ts(&f); + ui.bookmarkMenu->addSeparator(); + while (!ts.atEnd()) { + QString title = ts.readLine(); + QString link = ts.readLine(); + bookmarks.insert(ui.bookmarkMenu->addAction(title), link); + } +} + +void MainWindow::showBookmark(QAction *action) +{ + if (bookmarks.contains(action)) + showLink(bookmarks.value(action)); +} + +void MainWindow::showLinkFromClient(const QString &link) +{ + setWindowState(windowState() & ~Qt::WindowMinimized); + raise(); + activateWindow(); + QString l = MainWindow::urlifyFileName(link); + showLink(l); + if (isMinimized()) + showNormal(); +} + +void MainWindow::showLink(const QString &link) +{ + if(link.isEmpty()) + qWarning("The link is empty!"); + + // don't fill the history with the same url more then once + if (link == tabs->currentBrowser()->source().toString()) + return; + + QUrl url(link); + QFileInfo fi(url.toLocalFile()); + tabs->setSource(url.toString()); + tabs->currentBrowser()->setFocus(); +} + +void MainWindow::showLinks(const QStringList &links) +{ + if (links.size() == 0) { + qWarning("MainWindow::showLinks() - Empty link"); + return; + } + + if (links.size() == 1) { + showLink(MainWindow::urlifyFileName(links.first())); + return; + } + + QStringList::ConstIterator it = links.begin(); + // Initial showing, The tab is empty so update that without creating it first + if (!tabs->currentBrowser()->source().isValid()) { + QPair browser; + browser.first = tabs->currentBrowser(); + browser.second = links.first(); + pendingBrowsers.append(browser); + tabs->setTitle(tabs->currentBrowser(), tr("...")); + } + ++it; + + while(it != links.end()) { + QPair browser; + browser.first = tabs->newBackgroundTab(); + browser.second = *it; + pendingBrowsers.append(browser); + ++it; + } + + startTimer(50); + return; +} + +void MainWindow::removePendingBrowser(HelpWindow *win) +{ + if (!pendingBrowsers.count()) + return; + + QMutableListIterator > it(pendingBrowsers); + while (it.hasNext()) { + QPair browser = it.next(); + if (browser.first == win) { + it.remove(); + break; + } + } +} + +void MainWindow::timerEvent(QTimerEvent *e) +{ + QPair browser = pendingBrowsers.first(); + pendingBrowsers.pop_front(); + + if (pendingBrowsers.size() == 0) + killTimer(e->timerId()); + + browser.first->setSource(MainWindow::urlifyFileName(browser.second)); +} + +void MainWindow::showQtHelp() +{ + showLink(QLibraryInfo::location(QLibraryInfo::DocumentationPath) + + QLatin1String("/html/index.html")); +} + +MainWindow* MainWindow::newWindow() +{ + saveSettings(); + MainWindow *mw = new MainWindow; + mw->move(geometry().topLeft()); + if (isMaximized()) + mw->showMaximized(); + else + mw->show(); + mw->on_actionGoHome_triggered(); + return mw; +} + +void MainWindow::saveSettings() +{ + Config *config = Config::configuration(); + + config->setSideBarPage(helpDock->tabWidget()->currentIndex()); + config->setWindowGeometry(saveGeometry()); + config->setMainWindowState(saveState()); + + // Create list of the tab urls + QStringList lst; + QList browsers = tabs->browsers(); + foreach (HelpWindow *browser, browsers) + lst << browser->source().toString(); + config->setSource(lst); + config->save(); +} + +TabbedBrowser* MainWindow::browsers() const +{ + return tabs; +} + +void MainWindow::showSearchLink(const QString &link, const QStringList &terms) +{ + HelpWindow * hw = tabs->currentBrowser(); + hw->blockScrolling(true); + hw->setCursor(Qt::WaitCursor); + if (hw->source() == link) + hw->reload(); + else + showLink(link); + hw->setCursor(Qt::ArrowCursor); + + hw->viewport()->setUpdatesEnabled(false); + + QTextCharFormat marker; + marker.setForeground(Qt::red); + + QTextCursor firstHit; + + QTextCursor c = hw->textCursor(); + c.beginEditBlock(); + foreach (QString term, terms) { + c.movePosition(QTextCursor::Start); + hw->setTextCursor(c); + + bool found = hw->find(term, QTextDocument::FindWholeWords); + while (found) { + QTextCursor hit = hw->textCursor(); + if (firstHit.isNull() || hit.position() < firstHit.position()) + firstHit = hit; + + hit.mergeCharFormat(marker); + found = hw->find(term, QTextDocument::FindWholeWords); + } + } + + if (firstHit.isNull()) { + firstHit = hw->textCursor(); + firstHit.movePosition(QTextCursor::Start); + } + firstHit.clearSelection(); + c.endEditBlock(); + hw->setTextCursor(firstHit); + + hw->blockScrolling(false); + hw->viewport()->setUpdatesEnabled(true); +} + + +void MainWindow::showGoActionLink() +{ + const QObject *origin = sender(); + if(!origin || + QString::fromLatin1(origin->metaObject()->className()) != QString::fromLatin1("QAction")) + return; + + QAction *action = (QAction*) origin; + QString docfile = *(goActionDocFiles->find(action)); + showLink(MainWindow::urlifyFileName(docfile)); +} + +void MainWindow::on_actionHelpAssistant_triggered() +{ + showLink(Config::configuration()->assistantDocPath() + QLatin1String("/assistant-manual.html")); +} + +HelpDialog* MainWindow::helpDialog() const +{ + return helpDock; +} + +void MainWindow::backwardAvailable(bool enable) +{ + ui.actionGoPrevious->setEnabled(enable); +} + +void MainWindow::forwardAvailable(bool enable) +{ + ui.actionGoNext->setEnabled(enable); +} + +void MainWindow::updateProfileSettings() +{ + Config *config = Config::configuration(); +#ifndef Q_WS_MAC + setWindowIcon(config->applicationIcon()); +#endif + ui.helpMenu->clear(); + //ui.helpMenu->addAction(ui.actionHelpAssistant); + //ui.helpMenu->addSeparator(); + ui.helpMenu->addAction(ui.actionAboutAssistant); + if (!config->aboutApplicationMenuText().isEmpty()) + ui.helpMenu->addAction(ui.actionAboutApplication); + ui.helpMenu->addSeparator(); + ui.helpMenu->addAction(ui.actionHelpWhatsThis); + + ui.actionAboutApplication->setText(config->aboutApplicationMenuText()); + + if(!config->title().isNull()) + setWindowTitle(config->title()); +} + +void MainWindow::setupPopupMenu(QMenu *m) +{ + m->addAction(ui.actionNewWindow); + m->addAction(ui.actionOpenPage); + m->addAction(ui.actionClosePage); + m->addSeparator(); + m->addAction(ui.actionSaveAs); + m->addSeparator(); + m->addAction(ui.actionGoPrevious); + m->addAction(ui.actionGoNext); + m->addAction(ui.actionGoHome); + m->addSeparator(); + m->addAction(ui.actionZoomIn); + m->addAction(ui.actionZoomOut); + m->addSeparator(); + m->addAction(ui.actionEditCopy); + m->addAction(ui.actionEditFind); +} + +void MainWindow::on_actionSyncToc_triggered() +{ + HelpWindow *w = tabs->currentBrowser(); + if(w) { + qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); + QString link = w->source().toString(); + helpDock->locateContents(link); + helpDock->tabWidget()->setCurrentIndex(0); + qApp->restoreOverrideCursor(); + } +} + +void MainWindow::on_actionNewWindow_triggered() +{ + newWindow()->show(); +} + +void MainWindow::on_actionClose_triggered() +{ + close(); +} + +void MainWindow::on_actionHelpWhatsThis_triggered() +{ + QWhatsThis::enterWhatsThisMode(); +} + +void MainWindow::on_actionSaveAs_triggered() +{ + QString fileName; + QUrl url = tabs->currentBrowser()->source(); + if (url.isValid()) { + QFileInfo fi(url.toLocalFile()); + fileName = fi.fileName(); + } + fileName = QFileDialog::getSaveFileName(this, tr("Save Page"), fileName); + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::critical(this, tr("Save Page"), tr("Cannot open file for writing!")); + return; + } + + QFileInfo fi(fileName); + QString fn = fi.fileName(); + int i = fn.lastIndexOf(QLatin1Char('.')); + if (i > -1) + fn = fn.left(i); + QString relativeDestPath = fn + QLatin1String("_images"); + QDir destDir(fi.absolutePath() + QDir::separator() + relativeDestPath); + bool imgDirAvailable = destDir.exists(); + if (!imgDirAvailable) + imgDirAvailable = destDir.mkdir(destDir.absolutePath()); + + // save images + QTextDocument *doc = tabs->currentBrowser()->document()->clone(); + if (url.isValid() && imgDirAvailable) { + QTextBlock::iterator it; + for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) { + for (it = block.begin(); !(it.atEnd()); ++it) { + QTextFragment fragment = it.fragment(); + if (fragment.isValid()) { + QTextImageFormat fm = fragment.charFormat().toImageFormat(); + if (fm.isValid() && !fm.name().isEmpty()) { + QUrl imagePath = tabs->currentBrowser()->source().resolved(fm.name()); + if (!imagePath.isValid()) + continue; + QString from = imagePath.toLocalFile(); + QString destName = fm.name(); + int j = destName.lastIndexOf(QLatin1Char('/')); + if (j > -1) + destName = destName.mid(j+1); + QFileInfo info(from); + if (info.exists()) { + if (!QFile::copy(from, destDir.absolutePath() + + QDir::separator() + destName)) + continue; + fm.setName(QLatin1String("./") + relativeDestPath + QLatin1String("/") + destName); + QTextCursor cursor(doc); + cursor.setPosition(fragment.position()); + cursor.setPosition(fragment.position() + fragment.length(), + QTextCursor::KeepAnchor); + cursor.setCharFormat(fm); + } + } + } + } + } + } + QString src = doc->toHtml(QByteArray("utf-8")); + QTextStream s(&file); + s.setCodec("utf-8"); + s << src; + s.flush(); + file.close(); +} + +void MainWindow::showFontSettingsDialog() +{ + Config *config = Config::configuration(); + FontSettings settings = config->fontSettings(); + + { // It is important that the dialog be deleted before UI mode changes. + FontSettingsDialog dialog; + if (!dialog.showDialog(&settings)) + return; + } + + config->setFontPointSize(settings.browserFont.pointSizeF()); + config->setFontSettings(settings); + + updateApplicationFontSettings(settings); +} + +void MainWindow::updateApplicationFontSettings(FontSettings &settings) +{ + QFont font = settings.windowFont; + if (this->font() != font) + qApp->setFont(font, "QWidget"); + + font = settings.browserFont; + QList browsers = tabs->browsers(); + foreach (HelpWindow *browser, browsers) { + if (browser->font() != font) + browser->setFont(font); + } +} + +QT_END_NAMESPACE