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

Last change on this file since 555 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 27.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the Qt Assistant of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
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#endif
144}
145
146MainWindow::~MainWindow()
147{
148 windows.removeAll(this);
149 delete goActionDocFiles;
150}
151
152void MainWindow::setup()
153{
154 if(setupCompleted)
155 return;
156
157 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
158 statusBar()->showMessage(tr("Initializing Qt Assistant..."));
159 setupCompleted = true;
160 helpDock->initialize();
161 connect(ui.actionGoPrevious, SIGNAL(triggered()), tabs, SLOT(backward()));
162 connect(ui.actionGoNext, SIGNAL(triggered()), tabs, SLOT(forward()));
163 connect(ui.actionEditCopy, SIGNAL(triggered()), tabs, SLOT(copy()));
164 connect(ui.actionFileExit, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
165 connect(ui.actionAddBookmark, SIGNAL(triggered()),
166 helpDock, SLOT(addBookmark()));
167 connect(helpDock, SIGNAL(showLink(QString)),
168 this, SLOT(showLink(QString)));
169 connect(helpDock, SIGNAL(showSearchLink(QString,QStringList)),
170 this, SLOT(showSearchLink(QString,QStringList)));
171
172 connect(ui.bookmarkMenu, SIGNAL(triggered(QAction*)),
173 this, SLOT(showBookmark(QAction*)));
174 connect(ui.actionZoomIn, SIGNAL(triggered()), tabs, SLOT(zoomIn()));
175 connect(ui.actionZoomOut, SIGNAL(triggered()), tabs, SLOT(zoomOut()));
176
177 connect(ui.actionOpenPage, SIGNAL(triggered()), tabs, SLOT(newTab()));
178 connect(ui.actionClosePage, SIGNAL(triggered()), tabs, SLOT(closeTab()));
179 connect(ui.actionNextPage, SIGNAL(triggered()), tabs, SLOT(nextTab()));
180 connect(ui.actionPrevPage, SIGNAL(triggered()), tabs, SLOT(previousTab()));
181
182
183#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64)
184 QShortcut *acc = new QShortcut(tr("SHIFT+CTRL+="), this);
185 connect(acc, SIGNAL(activated()), ui.actionZoomIn, SIGNAL(triggered()));
186#endif
187
188 connect(new QShortcut(tr("Ctrl+T"), this), SIGNAL(activated()), helpDock, SLOT(toggleContents()));
189 connect(new QShortcut(tr("Ctrl+I"), this), SIGNAL(activated()), helpDock, SLOT(toggleIndex()));
190 connect(new QShortcut(tr("Ctrl+B"), this), SIGNAL(activated()), helpDock, SLOT(toggleBookmarks()));
191 connect(new QShortcut(tr("Ctrl+S"), this), SIGNAL(activated()), helpDock, SLOT(toggleSearch()));
192 connect(new QShortcut(tr("Ctrl+]"), this), SIGNAL(activated()), tabs, SLOT(nextTab()));
193 connect(new QShortcut(tr("Ctrl+["), this), SIGNAL(activated()), tabs, SLOT(previousTab()));
194
195 Config *config = Config::configuration();
196
197 setupBookmarkMenu();
198
199 QAction *viewsAction = createPopupMenu()->menuAction();
200 viewsAction->setText(tr("Views"));
201 ui.viewMenu->addAction(viewsAction);
202
203 const int tabIndex = config->sideBarPage();
204 helpDock->tabWidget()->setCurrentIndex(tabIndex);
205 // The tab index is 0 by default, so we need to force an upate
206 // to poulate the contents in this case.
207 if (tabIndex == 0)
208 helpDock->currentTabChanged(tabIndex);
209
210 ui.actionEditFind->setShortcut(QKeySequence::Find);
211 ui.actionEditFindNext->setShortcut(QKeySequence::FindNext);
212 ui.actionEditFindPrev->setShortcut(QKeySequence::FindPrevious);
213
214 QObject::connect(ui.actionEditFind, SIGNAL(triggered()), tabs, SLOT(find()));
215 QObject::connect(ui.actionEditFindNext, SIGNAL(triggered()), tabs, SLOT(findNext()));
216 QObject::connect(ui.actionEditFindPrev, SIGNAL(triggered()), tabs, SLOT(findPrevious()));
217 connect(ui.actionEditFont_Settings, SIGNAL(triggered()), this, SLOT(showFontSettingsDialog()));
218
219 qApp->restoreOverrideCursor();
220 ui.actionGoPrevious->setEnabled(false);
221 ui.actionGoNext->setEnabled(false);
222 ui.actionEditCopy->setEnabled(false);
223
224 // set the current selected item in the treeview
225 helpDialog()->locateContents(tabs->currentBrowser()->source().toString());
226 connect(tabs, SIGNAL(browserUrlChanged(QString)), helpDock, SLOT(locateContents(QString)));
227}
228
229void MainWindow::browserTabChanged()
230{
231 HelpWindow *win = tabs->currentBrowser();
232 if (win) {
233 QTextCursor cursor(win->textCursor());
234 ui.actionEditCopy->setEnabled(cursor.hasSelection());
235 ui.actionGoPrevious->setEnabled(win->isBackwardAvailable());
236 ui.actionGoNext->setEnabled(win->isForwardAvailable());
237 }
238}
239
240void MainWindow::copyAvailable(bool yes)
241{
242 ui.actionEditCopy->setEnabled(yes);
243}
244
245void MainWindow::updateTabActions(int index)
246{
247 bool enabled = (index > 1) ? true : false;
248 ui.actionPrevPage->setEnabled(enabled);
249 ui.actionNextPage->setEnabled(enabled);
250 ui.actionClosePage->setEnabled(enabled);
251}
252
253void MainWindow::setupGoActions()
254{
255 Config *config = Config::configuration();
256 QStringList titles = config->docTitles();
257 QAction *action = 0;
258
259 static bool separatorInserted = false;
260
261 foreach (QAction *a, goActions) {
262 ui.goMenu->removeAction(a);
263 ui.goActionToolbar->removeAction(a);
264 }
265 qDeleteAll(goActions);
266 goActions.clear();
267 goActionDocFiles->clear();
268
269 int addCount = 0;
270
271 foreach (QString title, titles) {
272 QPixmap pix = config->docIcon(title);
273 if(!pix.isNull()) {
274 if(!separatorInserted) {
275 ui.goMenu->addSeparator();
276 separatorInserted = true;
277 }
278 action = new QAction(this);
279 action->setText(title);
280 action->setWhatsThis(tr("Displays the main page of a specific documentation set."));
281 action->setIcon(QIcon(pix));
282 ui.goMenu->addAction(action);
283 ui.goActionToolbar->addAction(action);
284 goActions.append(action);
285 goActionDocFiles->insert(action, config->indexPage(title));
286 connect(action, SIGNAL(triggered()),
287 this, SLOT(showGoActionLink()));
288 ++addCount;
289 }
290 }
291 if(!addCount)
292 ui.goActionToolbar->hide();
293 else
294 ui.goActionToolbar->show();
295
296}
297
298bool MainWindow::insertActionSeparator()
299{
300 ui.goMenu->addSeparator();
301 ui.Toolbar->addSeparator();
302 return true;
303}
304
305void MainWindow::closeEvent(QCloseEvent *e)
306{
307 saveSettings();
308 e->accept();
309}
310
311void MainWindow::about()
312{
313 QMessageBox box(this);
314
315 // TODO: Remove these variables for 4.6.0. Must keep this way for 4.5.x due to string freeze.
316 QString edition;
317 QString info;
318 QString moreInfo;
319
320 box.setText(QString::fromLatin1("<center><img src=\":/trolltech/assistant/images/assistant-128.png\">"
321 "<h3>%1</h3>"
322 "<p>Version %2 %3</p></center>"
323 "<p>%4</p>"
324 "<p>%5</p>"
325 "<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p>"
326 "<p>The program is provided AS IS with NO WARRANTY OF ANY KIND,"
327 " INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A"
328 " PARTICULAR PURPOSE.<p/>")
329 .arg(tr("Qt Assistant")).arg(QLatin1String(QT_VERSION_STR)).arg(edition).arg(info).arg(moreInfo));
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
401class PrintThread : public QThread
402{
403 QPrinter _printer;
404 QTextDocument *_document;
405
406public:
407 PrintThread(QObject *parent)
408 : QThread(parent), _printer(QPrinter::HighResolution), _document(0)
409 {
410 }
411 ~PrintThread()
412 {
413 wait();
414 }
415
416 QPrinter *printer()
417 {
418 return &_printer;
419 }
420
421 void start(QTextDocument *document)
422 {
423 _document = document->clone();
424 _document->moveToThread(this);
425 QThread::start();
426 }
427
428protected:
429 void run()
430 {
431 _document->print(printer());
432 delete _document;
433 _document = 0;
434 }
435};
436
437void MainWindow::on_actionFilePrint_triggered()
438{
439#ifndef QT_NO_PRINTER
440 if (!QFontDatabase::supportsThreadedFontRendering()) {
441 QPrinter printer(QPrinter::HighResolution);
442
443 QPrintDialog dlg(&printer, this);
444 if (dlg.exec() == QDialog::Accepted) {
445 qApp->setOverrideCursor(Qt::WaitCursor);
446 tabs->currentBrowser()->document()->print(&printer);
447 qApp->restoreOverrideCursor();
448 }
449 return;
450 }
451
452 PrintThread *thread = new PrintThread(this);
453
454 QPrintDialog dlg(thread->printer(), this);
455 if (dlg.exec() == QDialog::Accepted) {
456 connect(thread, SIGNAL(finished()), SLOT(printingFinished()));
457 connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
458
459 qApp->setOverrideCursor(Qt::BusyCursor);
460 thread->start(tabs->currentBrowser()->document());
461 } else {
462 delete thread;
463 }
464#else
465 Q_ASSERT("No printing support");
466#endif
467}
468
469void MainWindow::printingFinished()
470{
471 qApp->restoreOverrideCursor();
472}
473
474void MainWindow::updateBookmarkMenu()
475{
476 for(QList<MainWindow*>::Iterator it = windows.begin(); it != windows.end(); ++it)
477 (*it)->setupBookmarkMenu();
478}
479
480void MainWindow::setupBookmarkMenu()
481{
482 ui.bookmarkMenu->clear();
483 bookmarks.clear();
484 ui.bookmarkMenu->addAction(ui.actionAddBookmark);
485
486 QFile f(QDir::homePath() + QLatin1String("/.assistant/bookmarks.") +
487 Config::configuration()->profileName());
488 if (!f.open(QFile::ReadOnly))
489 return;
490 QTextStream ts(&f);
491 ui.bookmarkMenu->addSeparator();
492 while (!ts.atEnd()) {
493 QString title = ts.readLine();
494 QString link = ts.readLine();
495 bookmarks.insert(ui.bookmarkMenu->addAction(title), link);
496 }
497}
498
499void MainWindow::showBookmark(QAction *action)
500{
501 if (bookmarks.contains(action))
502 showLink(bookmarks.value(action));
503}
504
505void MainWindow::showLinkFromClient(const QString &link)
506{
507 setWindowState(windowState() & ~Qt::WindowMinimized);
508 raise();
509 activateWindow();
510 QString l = MainWindow::urlifyFileName(link);
511 showLink(l);
512 if (isMinimized())
513 showNormal();
514}
515
516void MainWindow::showLink(const QString &link)
517{
518 if(link.isEmpty())
519 qWarning("The link is empty!");
520
521 // don't fill the history with the same url more then once
522 if (link == tabs->currentBrowser()->source().toString())
523 return;
524
525 QUrl url(link);
526 QFileInfo fi(url.toLocalFile());
527 tabs->setSource(url.toString());
528 tabs->currentBrowser()->setFocus();
529}
530
531void MainWindow::showLinks(const QStringList &links)
532{
533 if (links.size() == 0) {
534 qWarning("MainWindow::showLinks() - Empty link");
535 return;
536 }
537
538 if (links.size() == 1) {
539 showLink(MainWindow::urlifyFileName(links.first()));
540 return;
541 }
542
543 QStringList::ConstIterator it = links.begin();
544 // Initial showing, The tab is empty so update that without creating it first
545 if (!tabs->currentBrowser()->source().isValid()) {
546 QPair<HelpWindow*, QString> browser;
547 browser.first = tabs->currentBrowser();
548 browser.second = links.first();
549 pendingBrowsers.append(browser);
550 tabs->setTitle(tabs->currentBrowser(), tr("..."));
551 }
552 ++it;
553
554 while(it != links.end()) {
555 QPair<HelpWindow*, QString> browser;
556 browser.first = tabs->newBackgroundTab();
557 browser.second = *it;
558 pendingBrowsers.append(browser);
559 ++it;
560 }
561
562 startTimer(50);
563 return;
564}
565
566void MainWindow::removePendingBrowser(HelpWindow *win)
567{
568 if (!pendingBrowsers.count())
569 return;
570
571 QMutableListIterator<QPair<HelpWindow*, QString> > it(pendingBrowsers);
572 while (it.hasNext()) {
573 QPair<HelpWindow*, QString> browser = it.next();
574 if (browser.first == win) {
575 it.remove();
576 break;
577 }
578 }
579}
580
581void MainWindow::timerEvent(QTimerEvent *e)
582{
583 QPair<HelpWindow*, QString> browser = pendingBrowsers.first();
584 pendingBrowsers.pop_front();
585
586 if (pendingBrowsers.size() == 0)
587 killTimer(e->timerId());
588
589 browser.first->setSource(MainWindow::urlifyFileName(browser.second));
590}
591
592void MainWindow::showQtHelp()
593{
594 showLink(QLibraryInfo::location(QLibraryInfo::DocumentationPath) +
595 QLatin1String("/html/index.html"));
596}
597
598MainWindow* MainWindow::newWindow()
599{
600 saveSettings();
601 MainWindow *mw = new MainWindow;
602 mw->move(geometry().topLeft());
603 if (isMaximized())
604 mw->showMaximized();
605 else
606 mw->show();
607 mw->on_actionGoHome_triggered();
608 return mw;
609}
610
611void MainWindow::saveSettings()
612{
613 Config *config = Config::configuration();
614
615 config->setSideBarPage(helpDock->tabWidget()->currentIndex());
616 config->setWindowGeometry(saveGeometry());
617 config->setMainWindowState(saveState());
618
619 // Create list of the tab urls
620 QStringList lst;
621 QList<HelpWindow*> browsers = tabs->browsers();
622 foreach (HelpWindow *browser, browsers)
623 lst << browser->source().toString();
624 config->setSource(lst);
625 config->save();
626}
627
628TabbedBrowser* MainWindow::browsers() const
629{
630 return tabs;
631}
632
633void MainWindow::showSearchLink(const QString &link, const QStringList &terms)
634{
635 HelpWindow * hw = tabs->currentBrowser();
636 hw->blockScrolling(true);
637 hw->setCursor(Qt::WaitCursor);
638 if (hw->source() == link)
639 hw->reload();
640 else
641 showLink(link);
642 hw->setCursor(Qt::ArrowCursor);
643
644 hw->viewport()->setUpdatesEnabled(false);
645
646 QTextCharFormat marker;
647 marker.setForeground(Qt::red);
648
649 QTextCursor firstHit;
650
651 QTextCursor c = hw->textCursor();
652 c.beginEditBlock();
653 foreach (QString term, terms) {
654 c.movePosition(QTextCursor::Start);
655 hw->setTextCursor(c);
656
657 bool found = hw->find(term, QTextDocument::FindWholeWords);
658 while (found) {
659 QTextCursor hit = hw->textCursor();
660 if (firstHit.isNull() || hit.position() < firstHit.position())
661 firstHit = hit;
662
663 hit.mergeCharFormat(marker);
664 found = hw->find(term, QTextDocument::FindWholeWords);
665 }
666 }
667
668 if (firstHit.isNull()) {
669 firstHit = hw->textCursor();
670 firstHit.movePosition(QTextCursor::Start);
671 }
672 firstHit.clearSelection();
673 c.endEditBlock();
674 hw->setTextCursor(firstHit);
675
676 hw->blockScrolling(false);
677 hw->viewport()->setUpdatesEnabled(true);
678}
679
680
681void MainWindow::showGoActionLink()
682{
683 const QObject *origin = sender();
684 if(!origin ||
685 QString::fromLatin1(origin->metaObject()->className()) != QString::fromLatin1("QAction"))
686 return;
687
688 QAction *action = (QAction*) origin;
689 QString docfile = *(goActionDocFiles->find(action));
690 showLink(MainWindow::urlifyFileName(docfile));
691}
692
693void MainWindow::on_actionHelpAssistant_triggered()
694{
695 showLink(Config::configuration()->assistantDocPath() + QLatin1String("/assistant-manual.html"));
696}
697
698HelpDialog* MainWindow::helpDialog() const
699{
700 return helpDock;
701}
702
703void MainWindow::backwardAvailable(bool enable)
704{
705 ui.actionGoPrevious->setEnabled(enable);
706}
707
708void MainWindow::forwardAvailable(bool enable)
709{
710 ui.actionGoNext->setEnabled(enable);
711}
712
713void MainWindow::updateProfileSettings()
714{
715 Config *config = Config::configuration();
716#ifndef Q_WS_MAC
717 setWindowIcon(config->applicationIcon());
718#endif
719 ui.helpMenu->clear();
720 //ui.helpMenu->addAction(ui.actionHelpAssistant);
721 //ui.helpMenu->addSeparator();
722 ui.helpMenu->addAction(ui.actionAboutAssistant);
723 if (!config->aboutApplicationMenuText().isEmpty())
724 ui.helpMenu->addAction(ui.actionAboutApplication);
725 ui.helpMenu->addSeparator();
726 ui.helpMenu->addAction(ui.actionHelpWhatsThis);
727
728 ui.actionAboutApplication->setText(config->aboutApplicationMenuText());
729
730 if(!config->title().isNull())
731 setWindowTitle(config->title());
732}
733
734void MainWindow::setupPopupMenu(QMenu *m)
735{
736 m->addAction(ui.actionNewWindow);
737 m->addAction(ui.actionOpenPage);
738 m->addAction(ui.actionClosePage);
739 m->addSeparator();
740 m->addAction(ui.actionSaveAs);
741 m->addSeparator();
742 m->addAction(ui.actionGoPrevious);
743 m->addAction(ui.actionGoNext);
744 m->addAction(ui.actionGoHome);
745 m->addSeparator();
746 m->addAction(ui.actionZoomIn);
747 m->addAction(ui.actionZoomOut);
748 m->addSeparator();
749 m->addAction(ui.actionEditCopy);
750 m->addAction(ui.actionEditFind);
751}
752
753void MainWindow::on_actionSyncToc_triggered()
754{
755 HelpWindow *w = tabs->currentBrowser();
756 if(w) {
757 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
758 QString link = w->source().toString();
759 helpDock->locateContents(link);
760 helpDock->tabWidget()->setCurrentIndex(0);
761 qApp->restoreOverrideCursor();
762 }
763}
764
765void MainWindow::on_actionNewWindow_triggered()
766{
767 newWindow()->show();
768}
769
770void MainWindow::on_actionClose_triggered()
771{
772 close();
773}
774
775void MainWindow::on_actionHelpWhatsThis_triggered()
776{
777 QWhatsThis::enterWhatsThisMode();
778}
779
780void MainWindow::on_actionSaveAs_triggered()
781{
782 QString fileName;
783 QUrl url = tabs->currentBrowser()->source();
784 if (url.isValid()) {
785 QFileInfo fi(url.toLocalFile());
786 fileName = fi.fileName();
787 }
788 fileName = QFileDialog::getSaveFileName(this, tr("Save Page"), fileName);
789 if (fileName.isEmpty())
790 return;
791
792 QFile file(fileName);
793 if (!file.open(QIODevice::WriteOnly)) {
794 QMessageBox::critical(this, tr("Save Page"), tr("Cannot open file for writing!"));
795 return;
796 }
797
798 QFileInfo fi(fileName);
799 QString fn = fi.fileName();
800 int i = fn.lastIndexOf(QLatin1Char('.'));
801 if (i > -1)
802 fn = fn.left(i);
803 QString relativeDestPath = fn + QLatin1String("_images");
804 QDir destDir(fi.absolutePath() + QDir::separator() + relativeDestPath);
805 bool imgDirAvailable = destDir.exists();
806 if (!imgDirAvailable)
807 imgDirAvailable = destDir.mkdir(destDir.absolutePath());
808
809 // save images
810 QTextDocument *doc = tabs->currentBrowser()->document()->clone();
811 if (url.isValid() && imgDirAvailable) {
812 QTextBlock::iterator it;
813 for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) {
814 for (it = block.begin(); !(it.atEnd()); ++it) {
815 QTextFragment fragment = it.fragment();
816 if (fragment.isValid()) {
817 QTextImageFormat fm = fragment.charFormat().toImageFormat();
818 if (fm.isValid() && !fm.name().isEmpty()) {
819 QUrl imagePath = tabs->currentBrowser()->source().resolved(fm.name());
820 if (!imagePath.isValid())
821 continue;
822 QString from = imagePath.toLocalFile();
823 QString destName = fm.name();
824 int j = destName.lastIndexOf(QLatin1Char('/'));
825 if (j > -1)
826 destName = destName.mid(j+1);
827 QFileInfo info(from);
828 if (info.exists()) {
829 if (!QFile::copy(from, destDir.absolutePath()
830 + QDir::separator() + destName))
831 continue;
832 fm.setName(QLatin1String("./") + relativeDestPath + QLatin1String("/") + destName);
833 QTextCursor cursor(doc);
834 cursor.setPosition(fragment.position());
835 cursor.setPosition(fragment.position() + fragment.length(),
836 QTextCursor::KeepAnchor);
837 cursor.setCharFormat(fm);
838 }
839 }
840 }
841 }
842 }
843 }
844 QString src = doc->toHtml(QByteArray("utf-8"));
845 QTextStream s(&file);
846 s.setCodec("utf-8");
847 s << src;
848 s.flush();
849 file.close();
850}
851
852void MainWindow::showFontSettingsDialog()
853{
854 Config *config = Config::configuration();
855 FontSettings settings = config->fontSettings();
856
857 { // It is important that the dialog be deleted before UI mode changes.
858 FontSettingsDialog dialog;
859 if (!dialog.showDialog(&settings))
860 return;
861 }
862
863 config->setFontPointSize(settings.browserFont.pointSizeF());
864 config->setFontSettings(settings);
865
866 updateApplicationFontSettings(settings);
867}
868
869void MainWindow::updateApplicationFontSettings(FontSettings &settings)
870{
871 QFont font = settings.windowFont;
872 if (this->font() != font)
873 qApp->setFont(font, "QWidget");
874
875 font = settings.browserFont;
876 QList<HelpWindow*> browsers = tabs->browsers();
877 foreach (HelpWindow *browser, browsers) {
878 if (browser->font() != font)
879 browser->setFont(font);
880 }
881}
882
883QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.