source: trunk/tools/assistant/compat/mainwindow.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 27.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the Qt Assistant of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "mainwindow.h"
43#include "tabbedbrowser.h"
44#include "helpdialog.h"
45#include "config.h"
46#include "fontsettingsdialog.h"
47
48#include <QDockWidget>
49#include <QDir>
50#include <QTimer>
51#include <QStatusBar>
52#include <QShortcut>
53#include <QMessageBox>
54#include <QPainter>
55#include <QEventLoop>
56#include <QtEvents>
57#include <QFontDatabase>
58#include <QWhatsThis>
59#include <QTextDocumentFragment>
60#include <QLibraryInfo>
61#include <QPrinter>
62#include <QPrintDialog>
63#include <QAbstractTextDocumentLayout>
64#include <QTextDocument>
65#include <QTextObject>
66#include <QFileDialog>
67#include <QThread>
68
69QT_BEGIN_NAMESPACE
70
71QList<MainWindow*> MainWindow::windows;
72
73#if defined(Q_WS_WIN)
74extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;
75#endif
76
77MainWindow::MainWindow()
78{
79 setUnifiedTitleAndToolBarOnMac(true);
80 ui.setupUi(this);
81
82#if defined(Q_WS_WIN)
83 // Workaround for QMimeSourceFactory failing in QFileInfo::isReadable() for
84 // certain user configs. See task: 34372
85 qt_ntfs_permission_lookup = 0;
86#endif
87 setupCompleted = false;
88
89 goActions = QList<QAction*>();
90 goActionDocFiles = new QMap<QAction*,QString>;
91
92 windows.append(this);
93 tabs = new TabbedBrowser(this);
94 connect(tabs, SIGNAL(tabCountChanged(int)), this, SLOT(updateTabActions(int)));
95 setCentralWidget(tabs);
96
97 Config *config = Config::configuration();
98
99 updateProfileSettings();
100
101 dw = new QDockWidget(this);
102 dw->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
103 dw->setWindowTitle(tr("Sidebar"));
104 dw->setObjectName(QLatin1String("sidebar"));
105 helpDock = new HelpDialog(dw, this);
106 dw->setWidget(helpDock);
107
108 addDockWidget(Qt::LeftDockWidgetArea, dw);
109
110 // read geometry configuration
111 setupGoActions();
112
113 restoreGeometry(config->windowGeometry());
114 restoreState(config->mainWindowState());
115 if (config->sideBarHidden())
116 dw->hide();
117
118 tabs->setup();
119 QTimer::singleShot(0, this, SLOT(setup()));
120#if defined(Q_WS_MAC)
121 QMenu *windowMenu = new QMenu(tr("&Window"), this);
122 menuBar()->insertMenu(ui.helpMenu->menuAction(), windowMenu);
123 windowMenu->addAction(tr("Minimize"), this,
124 SLOT(showMinimized()), QKeySequence(tr("Ctrl+M")));
125 // Use the same forward and backward browser shortcuts as Safari and Internet Explorer do
126 // on the Mac. This means that if you have access to one of those cool Intellimice, the thing
127 // works just fine, since that's how Microsoft hacked it.
128 ui.actionGoPrevious->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Left));
129 ui.actionGoNext->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Right));
130
131 static const QLatin1String MacIconPath(":/trolltech/assistant/images/mac");
132 ui.actionGoNext->setIcon(QIcon(MacIconPath + QLatin1String("/next.png")));
133 ui.actionGoPrevious->setIcon(QIcon(MacIconPath + QLatin1String("/prev.png")));
134 ui.actionGoHome->setIcon(QIcon(MacIconPath + QLatin1String("/home.png")));
135 ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png")));
136 ui.actionEditCopy->setIcon(QIcon(MacIconPath + QLatin1String("/editcopy.png")));
137 ui.actionEditFind->setIcon(QIcon(MacIconPath + QLatin1String("/find.png")));
138 ui.actionFilePrint->setIcon(QIcon(MacIconPath + QLatin1String("/print.png")));
139 ui.actionZoomOut->setIcon(QIcon(MacIconPath + QLatin1String("/zoomout.png")));
140 ui.actionZoomIn->setIcon(QIcon(MacIconPath + QLatin1String("/zoomin.png")));
141 ui.actionSyncToc->setIcon(QIcon(MacIconPath + QLatin1String("/synctoc.png")));
142 ui.actionHelpWhatsThis->setIcon(QIcon(MacIconPath + QLatin1String("/whatsthis.png")));
143#elif defined(Q_WS_X11)
144 ui.actionGoNext->setIcon(QIcon::fromTheme("go-next" , ui.actionGoNext->icon()));
145 ui.actionGoPrevious->setIcon(QIcon::fromTheme("go-previous" , ui.actionGoPrevious->icon()));
146 ui.actionGoHome->setIcon(QIcon::fromTheme("user-home" , ui.actionGoHome->icon()));
147 ui.actionEditCopy->setIcon(QIcon::fromTheme("edit-copy" , ui.actionEditCopy->icon()));
148 ui.actionEditFind->setIcon(QIcon::fromTheme("edit-find" , ui.actionEditFind->icon()));
149 ui.actionFilePrint->setIcon(QIcon::fromTheme("document-print" , ui.actionFilePrint->icon()));
150 ui.actionZoomOut->setIcon(QIcon::fromTheme("zoom-out" , ui.actionZoomOut->icon()));
151 ui.actionZoomIn->setIcon(QIcon::fromTheme("zoom-in" , ui.actionZoomIn->icon()));
152 ui.actionSyncToc->setIcon(QIcon::fromTheme("view-refresh" , ui.actionSyncToc->icon()));
153#endif
154}
155
156MainWindow::~MainWindow()
157{
158 windows.removeAll(this);
159 delete goActionDocFiles;
160}
161
162void MainWindow::setup()
163{
164 if(setupCompleted)
165 return;
166
167 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
168 statusBar()->showMessage(tr("Initializing Qt Assistant..."));
169 setupCompleted = true;
170 helpDock->initialize();
171 connect(ui.actionGoPrevious, SIGNAL(triggered()), tabs, SLOT(backward()));
172 connect(ui.actionGoNext, SIGNAL(triggered()), tabs, SLOT(forward()));
173 connect(ui.actionEditCopy, SIGNAL(triggered()), tabs, SLOT(copy()));
174 connect(ui.actionFileExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
175 connect(ui.actionAddBookmark, SIGNAL(triggered()),
176 helpDock, SLOT(addBookmark()));
177 connect(helpDock, SIGNAL(showLink(QString)),
178 this, SLOT(showLink(QString)));
179 connect(helpDock, SIGNAL(showSearchLink(QString,QStringList)),
180 this, SLOT(showSearchLink(QString,QStringList)));
181
182 connect(ui.bookmarkMenu, SIGNAL(triggered(QAction*)),
183 this, SLOT(showBookmark(QAction*)));
184 connect(ui.actionZoomIn, SIGNAL(triggered()), tabs, SLOT(zoomIn()));
185 connect(ui.actionZoomOut, SIGNAL(triggered()), tabs, SLOT(zoomOut()));
186
187 connect(ui.actionOpenPage, SIGNAL(triggered()), tabs, SLOT(newTab()));
188 connect(ui.actionClosePage, SIGNAL(triggered()), tabs, SLOT(closeTab()));
189 connect(ui.actionNextPage, SIGNAL(triggered()), tabs, SLOT(nextTab()));
190 connect(ui.actionPrevPage, SIGNAL(triggered()), tabs, SLOT(previousTab()));
191
192
193#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64)
194 QShortcut *acc = new QShortcut(tr("SHIFT+CTRL+="), this);
195 connect(acc, SIGNAL(activated()), ui.actionZoomIn, SIGNAL(triggered()));
196#endif
197
198 connect(new QShortcut(tr("Ctrl+T"), this), SIGNAL(activated()), helpDock, SLOT(toggleContents()));
199 connect(new QShortcut(tr("Ctrl+I"), this), SIGNAL(activated()), helpDock, SLOT(toggleIndex()));
200 connect(new QShortcut(tr("Ctrl+B"), this), SIGNAL(activated()), helpDock, SLOT(toggleBookmarks()));
201 connect(new QShortcut(tr("Ctrl+S"), this), SIGNAL(activated()), helpDock, SLOT(toggleSearch()));
202 connect(new QShortcut(tr("Ctrl+]"), this), SIGNAL(activated()), tabs, SLOT(nextTab()));
203 connect(new QShortcut(tr("Ctrl+["), this), SIGNAL(activated()), tabs, SLOT(previousTab()));
204
205 Config *config = Config::configuration();
206
207 setupBookmarkMenu();
208
209 QAction *viewsAction = createPopupMenu()->menuAction();
210 viewsAction->setText(tr("Views"));
211 ui.viewMenu->addAction(viewsAction);
212
213 const int tabIndex = config->sideBarPage();
214 helpDock->tabWidget()->setCurrentIndex(tabIndex);
215 // The tab index is 0 by default, so we need to force an upate
216 // to poulate the contents in this case.
217 if (tabIndex == 0)
218 helpDock->currentTabChanged(tabIndex);
219
220 ui.actionEditFind->setShortcut(QKeySequence::Find);
221 ui.actionEditFindNext->setShortcut(QKeySequence::FindNext);
222 ui.actionEditFindPrev->setShortcut(QKeySequence::FindPrevious);
223
224 QObject::connect(ui.actionEditFind, SIGNAL(triggered()), tabs, SLOT(find()));
225 QObject::connect(ui.actionEditFindNext, SIGNAL(triggered()), tabs, SLOT(findNext()));
226 QObject::connect(ui.actionEditFindPrev, SIGNAL(triggered()), tabs, SLOT(findPrevious()));
227 connect(ui.actionEditFont_Settings, SIGNAL(triggered()), this, SLOT(showFontSettingsDialog()));
228
229 qApp->restoreOverrideCursor();
230 ui.actionGoPrevious->setEnabled(false);
231 ui.actionGoNext->setEnabled(false);
232 ui.actionEditCopy->setEnabled(false);
233
234 // set the current selected item in the treeview
235 helpDialog()->locateContents(tabs->currentBrowser()->source().toString());
236 connect(tabs, SIGNAL(browserUrlChanged(QString)), helpDock, SLOT(locateContents(QString)));
237}
238
239void MainWindow::browserTabChanged()
240{
241 HelpWindow *win = tabs->currentBrowser();
242 if (win) {
243 QTextCursor cursor(win->textCursor());
244 ui.actionEditCopy->setEnabled(cursor.hasSelection());
245 ui.actionGoPrevious->setEnabled(win->isBackwardAvailable());
246 ui.actionGoNext->setEnabled(win->isForwardAvailable());
247 }
248}
249
250void MainWindow::copyAvailable(bool yes)
251{
252 ui.actionEditCopy->setEnabled(yes);
253}
254
255void MainWindow::updateTabActions(int index)
256{
257 bool enabled = (index > 1) ? true : false;
258 ui.actionPrevPage->setEnabled(enabled);
259 ui.actionNextPage->setEnabled(enabled);
260 ui.actionClosePage->setEnabled(enabled);
261}
262
263void MainWindow::setupGoActions()
264{
265 Config *config = Config::configuration();
266 QStringList titles = config->docTitles();
267 QAction *action = 0;
268
269 static bool separatorInserted = false;
270
271 foreach (QAction *a, goActions) {
272 ui.goMenu->removeAction(a);
273 ui.goActionToolbar->removeAction(a);
274 }
275 qDeleteAll(goActions);
276 goActions.clear();
277 goActionDocFiles->clear();
278
279 int addCount = 0;
280
281 foreach (QString title, titles) {
282 QPixmap pix = config->docIcon(title);
283 if(!pix.isNull()) {
284 if(!separatorInserted) {
285 ui.goMenu->addSeparator();
286 separatorInserted = true;
287 }
288 action = new QAction(this);
289 action->setText(title);
290 action->setWhatsThis(tr("Displays the main page of a specific documentation set."));
291 action->setIcon(QIcon(pix));
292 ui.goMenu->addAction(action);
293 ui.goActionToolbar->addAction(action);
294 goActions.append(action);
295 goActionDocFiles->insert(action, config->indexPage(title));
296 connect(action, SIGNAL(triggered()),
297 this, SLOT(showGoActionLink()));
298 ++addCount;
299 }
300 }
301 if(!addCount)
302 ui.goActionToolbar->hide();
303 else
304 ui.goActionToolbar->show();
305
306}
307
308bool MainWindow::insertActionSeparator()
309{
310 ui.goMenu->addSeparator();
311 ui.Toolbar->addSeparator();
312 return true;
313}
314
315void MainWindow::closeEvent(QCloseEvent *e)
316{
317 saveSettings();
318 e->accept();
319}
320
321void MainWindow::about()
322{
323 QMessageBox box(this);
324
325 box.setText(QString::fromLatin1("<center><img src=\":/trolltech/assistant/images/assistant-128.png\">"
326 "<h3>%1</h3>"
327 "<p>Version %2</p></center>"
328 "<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p>")
329 .arg(tr("Qt Assistant")).arg(QLatin1String(QT_VERSION_STR)));
330 box.setWindowTitle(tr("Qt Assistant"));
331 box.setIcon(QMessageBox::NoIcon);
332 box.exec();
333}
334
335void MainWindow::on_actionAboutApplication_triggered()
336{
337 QString url = Config::configuration()->aboutURL();
338 if (url == QLatin1String("about_qt")) {
339 QMessageBox::aboutQt(this, QLatin1String("Qt Assistant"));
340 return;
341 }
342 QString text;
343 if (url.startsWith(QLatin1String("file:")))
344 url = url.mid(5);
345 QFile file(url);
346 if(file.exists() && file.open(QFile::ReadOnly))
347 text = QString::fromUtf8(file.readAll());
348 if(text.isNull())
349 text = tr("Failed to open about application contents in file: '%1'").arg(url);
350
351 QFileInfo fi(file);
352 QString path = QDir::cleanPath(fi.absolutePath());
353 if (!QDir::searchPaths(QLatin1String("aboutImages")).contains(path))
354 QDir::addSearchPath(QLatin1String("aboutImages"), path);
355
356 QMessageBox box(this);
357 box.setText(text);
358 box.setWindowTitle(Config::configuration()->aboutApplicationMenuText());
359 box.setIcon(QMessageBox::NoIcon);
360 box.exec();
361}
362
363void MainWindow::on_actionAboutAssistant_triggered()
364{
365 about();
366}
367
368void MainWindow::on_actionGoHome_triggered()
369{
370 QString home = MainWindow::urlifyFileName(Config::configuration()->homePage());
371 showLink(home);
372}
373
374QString MainWindow::urlifyFileName(const QString &fileName)
375{
376 QString name = fileName;
377 QUrl url(name);
378
379#if defined(Q_OS_WIN32)
380 if (!url.isValid() || url.scheme().isEmpty() || url.scheme().toLower() != QLatin1String("file:")) {
381 int i = name.indexOf(QLatin1Char('#'));
382 QString anchor = name.mid(i);
383 name = name.toLower();
384 if (i > -1)
385 name.replace(i, anchor.length(), anchor);
386 name.replace(QLatin1Char('\\'), QLatin1Char('/'));
387 foreach (QFileInfo drive, QDir::drives()) {
388 if (name.startsWith(drive.absolutePath().toLower())) {
389 name = QLatin1String("file:") + name;
390 break;
391 }
392 }
393 }
394#else
395 if (!url.isValid() || url.scheme().isEmpty())
396 name.prepend(QLatin1String("file:"));
397#endif
398 return name;
399}
400
401#ifndef QT_NO_PRINTER
402class PrintThread : public QThread
403{
404 QPrinter _printer;
405 QTextDocument *_document;
406
407public:
408 PrintThread(QObject *parent)
409 : QThread(parent), _printer(QPrinter::HighResolution), _document(0)
410 {
411 }
412 ~PrintThread()
413 {
414 wait();
415 }
416
417 QPrinter *printer()
418 {
419 return &_printer;
420 }
421
422 void start(QTextDocument *document)
423 {
424 _document = document->clone();
425 _document->moveToThread(this);
426 QThread::start();
427 }
428
429protected:
430 void run()
431 {
432 _document->print(printer());
433 delete _document;
434 _document = 0;
435 }
436};
437#endif //QT_NO_PRINTER
438
439void MainWindow::on_actionFilePrint_triggered()
440{
441#ifndef QT_NO_PRINTER
442 if (!QFontDatabase::supportsThreadedFontRendering()) {
443 QPrinter printer(QPrinter::HighResolution);
444
445 QPrintDialog dlg(&printer, this);
446 if (dlg.exec() == QDialog::Accepted) {
447 qApp->setOverrideCursor(Qt::WaitCursor);
448 tabs->currentBrowser()->document()->print(&printer);
449 qApp->restoreOverrideCursor();
450 }
451 return;
452 }
453
454 PrintThread *thread = new PrintThread(this);
455
456 QPrintDialog dlg(thread->printer(), this);
457 if (dlg.exec() == QDialog::Accepted) {
458 connect(thread, SIGNAL(finished()), SLOT(printingFinished()));
459 connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
460
461 qApp->setOverrideCursor(Qt::BusyCursor);
462 thread->start(tabs->currentBrowser()->document());
463 } else {
464 delete thread;
465 }
466#else
467 Q_ASSERT("No printing support");
468#endif
469}
470
471void MainWindow::printingFinished()
472{
473 qApp->restoreOverrideCursor();
474}
475
476void MainWindow::updateBookmarkMenu()
477{
478 for(QList<MainWindow*>::Iterator it = windows.begin(); it != windows.end(); ++it)
479 (*it)->setupBookmarkMenu();
480}
481
482void MainWindow::setupBookmarkMenu()
483{
484 ui.bookmarkMenu->clear();
485 bookmarks.clear();
486 ui.bookmarkMenu->addAction(ui.actionAddBookmark);
487
488 QFile f(QDir::homePath() + QLatin1String("/.assistant/bookmarks.") +
489 Config::configuration()->profileName());
490 if (!f.open(QFile::ReadOnly))
491 return;
492 QTextStream ts(&f);
493 ui.bookmarkMenu->addSeparator();
494 while (!ts.atEnd()) {
495 QString title = ts.readLine();
496 QString link = ts.readLine();
497 bookmarks.insert(ui.bookmarkMenu->addAction(title), link);
498 }
499}
500
501void MainWindow::showBookmark(QAction *action)
502{
503 if (bookmarks.contains(action))
504 showLink(bookmarks.value(action));
505}
506
507void MainWindow::showLinkFromClient(const QString &link)
508{
509 setWindowState(windowState() & ~Qt::WindowMinimized);
510 raise();
511 activateWindow();
512 QString l = MainWindow::urlifyFileName(link);
513 showLink(l);
514 if (isMinimized())
515 showNormal();
516}
517
518void MainWindow::showLink(const QString &link)
519{
520 if(link.isEmpty())
521 qWarning("The link is empty!");
522
523 // don't fill the history with the same url more then once
524 if (link == tabs->currentBrowser()->source().toString())
525 return;
526
527 QUrl url(link);
528 QFileInfo fi(url.toLocalFile());
529 tabs->setSource(url.toString());
530 tabs->currentBrowser()->setFocus();
531}
532
533void MainWindow::showLinks(const QStringList &links)
534{
535 if (links.size() == 0) {
536 qWarning("MainWindow::showLinks() - Empty link");
537 return;
538 }
539
540 if (links.size() == 1) {
541 showLink(MainWindow::urlifyFileName(links.first()));
542 return;
543 }
544
545 QStringList::ConstIterator it = links.begin();
546 // Initial showing, The tab is empty so update that without creating it first
547 if (!tabs->currentBrowser()->source().isValid()) {
548 QPair<HelpWindow*, QString> browser;
549 browser.first = tabs->currentBrowser();
550 browser.second = links.first();
551 pendingBrowsers.append(browser);
552 tabs->setTitle(tabs->currentBrowser(), tr("..."));
553 }
554 ++it;
555
556 while(it != links.end()) {
557 QPair<HelpWindow*, QString> browser;
558 browser.first = tabs->newBackgroundTab();
559 browser.second = *it;
560 pendingBrowsers.append(browser);
561 ++it;
562 }
563
564 startTimer(50);
565 return;
566}
567
568void MainWindow::removePendingBrowser(HelpWindow *win)
569{
570 if (!pendingBrowsers.count())
571 return;
572
573 QMutableListIterator<QPair<HelpWindow*, QString> > it(pendingBrowsers);
574 while (it.hasNext()) {
575 QPair<HelpWindow*, QString> browser = it.next();
576 if (browser.first == win) {
577 it.remove();
578 break;
579 }
580 }
581}
582
583void MainWindow::timerEvent(QTimerEvent *e)
584{
585 QPair<HelpWindow*, QString> browser = pendingBrowsers.first();
586 pendingBrowsers.pop_front();
587
588 if (pendingBrowsers.size() == 0)
589 killTimer(e->timerId());
590
591 browser.first->setSource(MainWindow::urlifyFileName(browser.second));
592}
593
594void MainWindow::showQtHelp()
595{
596 showLink(QLibraryInfo::location(QLibraryInfo::DocumentationPath) +
597 QLatin1String("/html/index.html"));
598}
599
600MainWindow* MainWindow::newWindow()
601{
602 saveSettings();
603 MainWindow *mw = new MainWindow;
604 mw->move(geometry().topLeft());
605 if (isMaximized())
606 mw->showMaximized();
607 else
608 mw->show();
609 mw->on_actionGoHome_triggered();
610 return mw;
611}
612
613void MainWindow::saveSettings()
614{
615 Config *config = Config::configuration();
616
617 config->setSideBarPage(helpDock->tabWidget()->currentIndex());
618 config->setWindowGeometry(saveGeometry());
619 config->setMainWindowState(saveState());
620
621 // Create list of the tab urls
622 QStringList lst;
623 QList<HelpWindow*> browsers = tabs->browsers();
624 foreach (HelpWindow *browser, browsers)
625 lst << browser->source().toString();
626 config->setSource(lst);
627 config->save();
628}
629
630TabbedBrowser* MainWindow::browsers() const
631{
632 return tabs;
633}
634
635void MainWindow::showSearchLink(const QString &link, const QStringList &terms)
636{
637 HelpWindow * hw = tabs->currentBrowser();
638 hw->blockScrolling(true);
639 hw->setCursor(Qt::WaitCursor);
640 if (hw->source() == link)
641 hw->reload();
642 else
643 showLink(link);
644 hw->setCursor(Qt::ArrowCursor);
645
646 hw->viewport()->setUpdatesEnabled(false);
647
648 QTextCharFormat marker;
649 marker.setForeground(Qt::red);
650
651 QTextCursor firstHit;
652
653 QTextCursor c = hw->textCursor();
654 c.beginEditBlock();
655 foreach (QString term, terms) {
656 c.movePosition(QTextCursor::Start);
657 hw->setTextCursor(c);
658
659 bool found = hw->find(term, QTextDocument::FindWholeWords);
660 while (found) {
661 QTextCursor hit = hw->textCursor();
662 if (firstHit.isNull() || hit.position() < firstHit.position())
663 firstHit = hit;
664
665 hit.mergeCharFormat(marker);
666 found = hw->find(term, QTextDocument::FindWholeWords);
667 }
668 }
669
670 if (firstHit.isNull()) {
671 firstHit = hw->textCursor();
672 firstHit.movePosition(QTextCursor::Start);
673 }
674 firstHit.clearSelection();
675 c.endEditBlock();
676 hw->setTextCursor(firstHit);
677
678 hw->blockScrolling(false);
679 hw->viewport()->setUpdatesEnabled(true);
680}
681
682
683void MainWindow::showGoActionLink()
684{
685 const QObject *origin = sender();
686 if(!origin ||
687 QString::fromLatin1(origin->metaObject()->className()) != QString::fromLatin1("QAction"))
688 return;
689
690 QAction *action = (QAction*) origin;
691 QString docfile = *(goActionDocFiles->find(action));
692 showLink(MainWindow::urlifyFileName(docfile));
693}
694
695void MainWindow::on_actionHelpAssistant_triggered()
696{
697 showLink(Config::configuration()->assistantDocPath() + QLatin1String("/assistant-manual.html"));
698}
699
700HelpDialog* MainWindow::helpDialog() const
701{
702 return helpDock;
703}
704
705void MainWindow::backwardAvailable(bool enable)
706{
707 ui.actionGoPrevious->setEnabled(enable);
708}
709
710void MainWindow::forwardAvailable(bool enable)
711{
712 ui.actionGoNext->setEnabled(enable);
713}
714
715void MainWindow::updateProfileSettings()
716{
717 Config *config = Config::configuration();
718#ifndef Q_WS_MAC
719 setWindowIcon(config->applicationIcon());
720#endif
721 ui.helpMenu->clear();
722 //ui.helpMenu->addAction(ui.actionHelpAssistant);
723 //ui.helpMenu->addSeparator();
724 ui.helpMenu->addAction(ui.actionAboutAssistant);
725 if (!config->aboutApplicationMenuText().isEmpty())
726 ui.helpMenu->addAction(ui.actionAboutApplication);
727 ui.helpMenu->addSeparator();
728 ui.helpMenu->addAction(ui.actionHelpWhatsThis);
729
730 ui.actionAboutApplication->setText(config->aboutApplicationMenuText());
731
732 if(!config->title().isNull())
733 setWindowTitle(config->title());
734}
735
736void MainWindow::setupPopupMenu(QMenu *m)
737{
738 m->addAction(ui.actionNewWindow);
739 m->addAction(ui.actionOpenPage);
740 m->addAction(ui.actionClosePage);
741 m->addSeparator();
742 m->addAction(ui.actionSaveAs);
743 m->addSeparator();
744 m->addAction(ui.actionGoPrevious);
745 m->addAction(ui.actionGoNext);
746 m->addAction(ui.actionGoHome);
747 m->addSeparator();
748 m->addAction(ui.actionZoomIn);
749 m->addAction(ui.actionZoomOut);
750 m->addSeparator();
751 m->addAction(ui.actionEditCopy);
752 m->addAction(ui.actionEditFind);
753}
754
755void MainWindow::on_actionSyncToc_triggered()
756{
757 HelpWindow *w = tabs->currentBrowser();
758 if(w) {
759 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
760 QString link = w->source().toString();
761 helpDock->locateContents(link);
762 helpDock->tabWidget()->setCurrentIndex(0);
763 qApp->restoreOverrideCursor();
764 }
765}
766
767void MainWindow::on_actionNewWindow_triggered()
768{
769 newWindow()->show();
770}
771
772void MainWindow::on_actionClose_triggered()
773{
774 close();
775}
776
777void MainWindow::on_actionHelpWhatsThis_triggered()
778{
779 QWhatsThis::enterWhatsThisMode();
780}
781
782void MainWindow::on_actionSaveAs_triggered()
783{
784 QString fileName;
785 QUrl url = tabs->currentBrowser()->source();
786 if (url.isValid()) {
787 QFileInfo fi(url.toLocalFile());
788 fileName = fi.fileName();
789 }
790 fileName = QFileDialog::getSaveFileName(this, tr("Save Page"), fileName);
791 if (fileName.isEmpty())
792 return;
793
794 QFile file(fileName);
795 if (!file.open(QIODevice::WriteOnly)) {
796 QMessageBox::critical(this, tr("Save Page"), tr("Cannot open file for writing!"));
797 return;
798 }
799
800 QFileInfo fi(fileName);
801 QString fn = fi.fileName();
802 int i = fn.lastIndexOf(QLatin1Char('.'));
803 if (i > -1)
804 fn = fn.left(i);
805 QString relativeDestPath = fn + QLatin1String("_images");
806 QDir destDir(fi.absolutePath() + QDir::separator() + relativeDestPath);
807 bool imgDirAvailable = destDir.exists();
808 if (!imgDirAvailable)
809 imgDirAvailable = destDir.mkdir(destDir.absolutePath());
810
811 // save images
812 QTextDocument *doc = tabs->currentBrowser()->document()->clone();
813 if (url.isValid() && imgDirAvailable) {
814 QTextBlock::iterator it;
815 for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) {
816 for (it = block.begin(); !(it.atEnd()); ++it) {
817 QTextFragment fragment = it.fragment();
818 if (fragment.isValid()) {
819 QTextImageFormat fm = fragment.charFormat().toImageFormat();
820 if (fm.isValid() && !fm.name().isEmpty()) {
821 QUrl imagePath = tabs->currentBrowser()->source().resolved(fm.name());
822 if (!imagePath.isValid())
823 continue;
824 QString from = imagePath.toLocalFile();
825 QString destName = fm.name();
826 int j = destName.lastIndexOf(QLatin1Char('/'));
827 if (j > -1)
828 destName = destName.mid(j+1);
829 QFileInfo info(from);
830 if (info.exists()) {
831 if (!QFile::copy(from, destDir.absolutePath()
832 + QDir::separator() + destName))
833 continue;
834 fm.setName(QLatin1String("./") + relativeDestPath + QLatin1String("/") + destName);
835 QTextCursor cursor(doc);
836 cursor.setPosition(fragment.position());
837 cursor.setPosition(fragment.position() + fragment.length(),
838 QTextCursor::KeepAnchor);
839 cursor.setCharFormat(fm);
840 }
841 }
842 }
843 }
844 }
845 }
846 QString src = doc->toHtml(QByteArray("utf-8"));
847 QTextStream s(&file);
848 s.setCodec("utf-8");
849 s << src;
850 s.flush();
851 file.close();
852}
853
854void MainWindow::showFontSettingsDialog()
855{
856 Config *config = Config::configuration();
857 FontSettings settings = config->fontSettings();
858
859 { // It is important that the dialog be deleted before UI mode changes.
860 FontSettingsDialog dialog;
861 if (!dialog.showDialog(&settings))
862 return;
863 }
864
865 config->setFontPointSize(settings.browserFont.pointSizeF());
866 config->setFontSettings(settings);
867
868 updateApplicationFontSettings(settings);
869}
870
871void MainWindow::updateApplicationFontSettings(FontSettings &settings)
872{
873 QFont font = settings.windowFont;
874 if (this->font() != font)
875 qApp->setFont(font, "QWidget");
876
877 font = settings.browserFont;
878 QList<HelpWindow*> browsers = tabs->browsers();
879 foreach (HelpWindow *browser, browsers) {
880 if (browser->font() != font)
881 browser->setFont(font);
882 }
883}
884
885QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.