source: terepaima/terepaima-0.4.16/sources/mainwindow.cpp @ 1f4adec

desarrollostretch
Last change on this file since 1f4adec was 1f4adec, checked in by aosorio <aosorio@…>, 8 years ago

Agregado proyecto base, esto luego del dh_make -f

  • Property mode set to 100644
File size: 129.3 KB
Line 
1/*
2
3Copyright 2014-2015 S. Razi Alavizadeh
4Copyright 2012-2015 Adam Reichold
5Copyright 2014 Dorian Scholz
6Copyright 2012 Michał Trybus
7Copyright 2012 Alexander Volkov
8
9This file is part of qpdfview.
10
11qpdfview is free software: you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation, either version 2 of the License, or
14(at your option) any later version.
15
16qpdfview is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with qpdfview.  If not, see <http://www.gnu.org/licenses/>.
23
24*/
25
26#include "mainwindow.h"
27
28#include <QApplication>
29#include <QCheckBox>
30#include <QClipboard>
31#include <QDateTime>
32#include <QDebug>
33#include <QDesktopServices>
34#include <QDockWidget>
35#include <QDragEnterEvent>
36#include <QFileDialog>
37#include <QHeaderView>
38#include <QInputDialog>
39#include <QMenuBar>
40#include <QMessageBox>
41#include <QMimeData>
42#include <QScrollBar>
43#include <QShortcut>
44#include <QStandardItemModel>
45#include <QTableView>
46#include <QTimer>
47#include <QToolBar>
48#include <QToolButton>
49#include <QUrl>
50#include <QVBoxLayout>
51#include <QWidgetAction>
52
53#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
54
55#include <QStandardPaths>
56
57#endif // QT_VERSION
58
59#include "model.h"
60#include "settings.h"
61#include "shortcuthandler.h"
62#include "thumbnailitem.h"
63#include "searchmodel.h"
64#include "searchitemdelegate.h"
65#include "documentview.h"
66#include "miscellaneous.h"
67#include "printdialog.h"
68#include "settingsdialog.h"
69#include "fontsdialog.h"
70#include "helpdialog.h"
71#include "recentlyusedmenu.h"
72#include "recentlyclosedmenu.h"
73#include "bookmarkmodel.h"
74#include "bookmarkmenu.h"
75#include "bookmarkdialog.h"
76#include "database.h"
77#include "Form.h"
78
79//********************************* POPPLER
80
81#include <stdio.h>
82#include <stdlib.h>
83#include <stddef.h>
84#include <string.h>
85#include <time.h>
86
87//#include "config.h"
88
89#include <poppler-config.h>
90
91#include "Object.h"
92#include "Array.h"
93#include "Page.h"
94#include "PDFDoc.h"
95#include "PDFDocFactory.h"
96#include "Error.h"
97#include "GlobalParams.h"
98#include "SignatureInfo.h"
99
100
101//********************************* POPPLER
102
103namespace
104{
105
106using namespace qpdfview;
107
108QModelIndex synchronizeOutlineView(int currentPage, const QAbstractItemModel* model, const QModelIndex& parent)
109{
110    for(int row = 0, rowCount = model->rowCount(parent); row < rowCount; ++row)
111    {
112        const QModelIndex index = model->index(row, 0, parent);
113
114        bool ok = false;
115        const int page = model->data(index, Model::Document::PageRole).toInt(&ok);
116
117        if(ok && page == currentPage)
118        {
119            return index;
120        }
121    }
122
123    for(int row = 0, rowCount = model->rowCount(parent); row < rowCount; ++row)
124    {
125        const QModelIndex index = model->index(row, 0, parent);
126        const QModelIndex match = synchronizeOutlineView(currentPage, model, index);
127
128        if(match.isValid())
129        {
130            return match;
131        }
132    }
133
134    return QModelIndex();
135}
136
137inline void setToolButtonMenu(QToolBar* toolBar, QAction* action, QMenu* menu)
138{
139    if(QToolButton* toolButton = qobject_cast< QToolButton* >(toolBar->widgetForAction(action)))
140    {
141        toolButton->setMenu(menu);
142    }
143}
144
145inline QAction* createTemporaryAction(QObject* parent, const QString& text, const QString& objectName)
146{
147    QAction* action = new QAction(text, parent);
148
149    action->setObjectName(objectName);
150
151    return action;
152}
153
154void addWidgetActions(QWidget* widget, const QStringList& actionNames, const QList< QAction* >& actions)
155{
156    foreach(const QString& actionName, actionNames)
157    {
158        if(actionName == QLatin1String("separator"))
159        {
160            QAction* separator = new QAction(widget);
161            separator->setSeparator(true);
162
163            widget->addAction(separator);
164
165            continue;
166        }
167
168        foreach(QAction* action, actions)
169        {
170            if(actionName == action->objectName())
171            {
172                widget->addAction(action);
173
174                break;
175            }
176        }
177    }
178}
179
180class SignalBlocker
181{
182public:
183    SignalBlocker(QObject* object) : m_object(object)
184    {
185        m_object->blockSignals(true);
186    }
187
188    ~SignalBlocker()
189    {
190        m_object->blockSignals(false);
191    }
192
193private:
194    Q_DISABLE_COPY(SignalBlocker)
195
196    QObject* m_object;
197
198};
199
200} // anonymous
201
202namespace qpdfview
203{
204
205class MainWindow::RestoreTab : public Database::RestoreTab
206{
207private:
208    MainWindow* that;
209
210public:
211    RestoreTab(MainWindow* that) : that(that) {}
212
213    DocumentView* operator()(const QString& absoluteFilePath) const
214    {
215        if(that->openInNewTab(absoluteFilePath, -1, QRectF(), true))
216        {
217            return that->currentTab();
218        }
219        else
220        {
221            return 0;
222        }
223    }
224
225};
226
227class MainWindow::TextValueMapper : public MappingSpinBox::TextValueMapper
228{
229private:
230    MainWindow* that;
231
232public:
233    TextValueMapper(MainWindow* that) : that(that) {}
234
235    QString textFromValue(int val, bool& ok) const
236    {
237        const DocumentView* currentTab = that->currentTab();
238
239        if(currentTab == 0 || !(currentTab->hasFrontMatter() || that->s_settings->mainWindow().usePageLabel()))
240        {
241            ok = false;
242            return QString();
243        }
244
245        ok = true;
246        return currentTab->pageLabelFromNumber(val);
247    }
248
249    int valueFromText(const QString& text, bool& ok) const
250    {
251        const DocumentView* currentTab = that->currentTab();
252
253        if(currentTab == 0 || !(currentTab->hasFrontMatter() || that->s_settings->mainWindow().usePageLabel()))
254        {
255            ok = false;
256            return 0;
257        }
258
259        const QString& prefix = that->m_currentPageSpinBox->prefix();
260        const QString& suffix = that->m_currentPageSpinBox->suffix();
261
262        int from = 0;
263        int size = text.size();
264
265        if(!prefix.isEmpty() && text.startsWith(prefix))
266        {
267            from += prefix.size();
268            size -= from;
269        }
270
271        if(!suffix.isEmpty() && text.endsWith(suffix))
272        {
273            size -= suffix.size();
274        }
275
276        const QString& trimmedText = text.mid(from, size).trimmed();
277
278        ok = true;
279        return currentTab->pageNumberFromLabel(trimmedText);
280    }
281
282};
283
284Settings* MainWindow::s_settings = 0;
285Database* MainWindow::s_database = 0;
286ShortcutHandler* MainWindow::s_shortcutHandler = 0;
287
288MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent),
289    m_outlineView(0),
290    m_thumbnailsView(0)
291{
292    if(s_settings == 0)
293    {
294        s_settings = Settings::instance();
295    }
296
297    if(s_shortcutHandler == 0)
298    {
299        s_shortcutHandler = ShortcutHandler::instance();
300    }
301
302    prepareStyle();
303
304    setAcceptDrops(true);
305
306    createWidgets();
307    createActions();
308    createToolBars();
309    createDocks();
310    createMenus();
311
312    restoreGeometry(s_settings->mainWindow().geometry());
313    restoreState(s_settings->mainWindow().state());
314
315    prepareDatabase();
316
317    on_tabWidget_currentChanged(m_tabWidget->currentIndex());
318}
319
320QSize MainWindow::sizeHint() const
321{
322    return QSize(600, 800);
323}
324
325QMenu* MainWindow::createPopupMenu()
326{
327    qDebug("createPopupMenu()");
328    QMenu* menu = new QMenu();
329
330    menu->addAction(m_fileToolBar->toggleViewAction());
331    menu->addAction(m_editToolBar->toggleViewAction());
332    menu->addAction(m_viewToolBar->toggleViewAction());
333    menu->addSeparator();
334    menu->addAction(m_outlineDock->toggleViewAction());
335    menu->addAction(m_propertiesDock->toggleViewAction());
336    menu->addAction(m_thumbnailsDock->toggleViewAction());
337    menu->addAction(m_bookmarksDock->toggleViewAction());
338    menu->addAction(m_detailsSignatureDock->toggleViewAction());
339
340    return menu;
341}
342
343void MainWindow::show()
344{
345    QMainWindow::show();
346
347    if(s_settings->mainWindow().restoreTabs())
348    {
349        s_database->restoreTabs(RestoreTab(this));
350    }
351
352    if(s_settings->mainWindow().restoreBookmarks())
353    {
354        s_database->restoreBookmarks();
355    }
356}
357
358
359bool MainWindow::open(const QString& filePath, int page, const QRectF& highlight, bool quiet)
360{
361    if(m_tabWidget->currentIndex() != -1)
362    {
363        saveModifications(currentTab());
364
365        if(currentTab()->open(filePath))
366        {
367            s_settings->mainWindow().setOpenPath(currentTab()->fileInfo().absolutePath());
368            m_recentlyUsedMenu->addOpenAction(currentTab()->fileInfo());
369
370            m_tabWidget->setTabText(m_tabWidget->currentIndex(), currentTab()->title());
371            m_tabWidget->setTabToolTip(m_tabWidget->currentIndex(), currentTab()->fileInfo().absoluteFilePath());
372
373            s_database->restorePerFileSettings(currentTab());
374            scheduleSaveTabs();
375
376            currentTab()->jumpToPage(page, false);
377            currentTab()->setFocus();
378
379            if(!highlight.isNull())
380            {
381                currentTab()->temporaryHighlight(page, highlight);
382            }
383
384            return true;
385        }
386        else
387        {
388            if(!quiet)
389            {
390                QMessageBox::warning(this, tr("Warning"), tr("Could not open '%1'.").arg(filePath));
391            }
392        }
393    }
394
395    return false;
396}
397
398bool MainWindow::openInNewTab(const QString& filePath, int page, const QRectF& highlight, bool quiet)
399{
400    DocumentView* newTab = new DocumentView(this);
401
402    if(newTab->open(filePath))
403    {
404        s_settings->mainWindow().setOpenPath(newTab->fileInfo().absolutePath());
405        m_recentlyUsedMenu->addOpenAction(newTab->fileInfo());
406
407        const int index = addTab(newTab);
408
409        QAction* tabAction = new QAction(m_tabWidget->tabText(index), newTab);
410        connect(tabAction, SIGNAL(triggered()), SLOT(on_tabAction_triggered()));
411
412        tabAction->setData(true); // Flag action for search-as-you-type
413
414        m_tabsMenu->addAction(tabAction);
415
416        on_thumbnails_dockLocationChanged(dockWidgetArea(m_thumbnailsDock));
417
418        connect(newTab, SIGNAL(documentChanged()), SLOT(on_currentTab_documentChanged()));
419        connect(newTab, SIGNAL(documentModified()), SLOT(on_currentTab_documentModified()));
420
421        connect(newTab, SIGNAL(numberOfPagesChanged(int)), SLOT(on_currentTab_numberOfPagesChaned(int)));
422        connect(newTab, SIGNAL(currentPageChanged(int)), SLOT(on_currentTab_currentPageChanged(int)));
423
424        connect(newTab, SIGNAL(canJumpChanged(bool,bool)), SLOT(on_currentTab_canJumpChanged(bool,bool)));
425
426        connect(newTab, SIGNAL(continuousModeChanged(bool)), SLOT(on_currentTab_continuousModeChanged(bool)));
427        connect(newTab, SIGNAL(layoutModeChanged(LayoutMode)), SLOT(on_currentTab_layoutModeChanged(LayoutMode)));
428        connect(newTab, SIGNAL(rightToLeftModeChanged(bool)), SLOT(on_currentTab_rightToLeftModeChanged(bool)));
429        connect(newTab, SIGNAL(scaleModeChanged(ScaleMode)), SLOT(on_currentTab_scaleModeChanged(ScaleMode)));
430        connect(newTab, SIGNAL(scaleFactorChanged(qreal)), SLOT(on_currentTab_scaleFactorChanged(qreal)));
431        connect(newTab, SIGNAL(rotationChanged(Rotation)), SLOT(on_currentTab_rotationChanged(Rotation)));
432
433        connect(newTab, SIGNAL(linkClicked(int)), SLOT(on_currentTab_linkClicked(int)));
434        connect(newTab, SIGNAL(linkClicked(bool,QString,int)), SLOT(on_currentTab_linkClicked(bool,QString,int)));
435
436        connect(newTab, SIGNAL(renderFlagsChanged(qpdfview::RenderFlags)), SLOT(on_currentTab_renderFlagsChanged(qpdfview::RenderFlags)));
437
438        connect(newTab, SIGNAL(invertColorsChanged(bool)), SLOT(on_currentTab_invertColorsChanged(bool)));
439        connect(newTab, SIGNAL(convertToGrayscaleChanged(bool)), SLOT(on_currentTab_convertToGrayscaleChanged(bool)));
440        connect(newTab, SIGNAL(trimMarginsChanged(bool)), SLOT(on_currentTab_trimMarginsChanged(bool)));
441
442        connect(newTab, SIGNAL(compositionModeChanged(CompositionMode)), SLOT(on_currentTab_compositionModeChanged(CompositionMode)));
443
444        connect(newTab, SIGNAL(highlightAllChanged(bool)), SLOT(on_currentTab_highlightAllChanged(bool)));
445        connect(newTab, SIGNAL(rubberBandModeChanged(RubberBandMode)), SLOT(on_currentTab_rubberBandModeChanged(RubberBandMode)));
446
447        connect(newTab, SIGNAL(searchFinished()), SLOT(on_currentTab_searchFinished()));
448        connect(newTab, SIGNAL(searchProgressChanged(int)), SLOT(on_currentTab_searchProgressChanged(int)));
449
450        connect(newTab, SIGNAL(customContextMenuRequested(QPoint)), SLOT(on_currentTab_customContextMenuRequested(QPoint)));
451
452        newTab->show();
453
454        s_database->restorePerFileSettings(newTab);
455        scheduleSaveTabs();
456
457        newTab->jumpToPage(page, false);
458        newTab->setFocus();
459
460        if(!highlight.isNull())
461        {
462            newTab->temporaryHighlight(page, highlight);
463        }
464
465        return true;
466    }
467    else
468    {
469        delete newTab;
470
471        if(!quiet)
472        {
473            QMessageBox::warning(this, tr("Warning"), tr("Could not open '%1'.").arg(filePath));
474        }
475    }
476
477    return false;
478}
479
480bool MainWindow::jumpToPageOrOpenInNewTab(const QString& filePath, int page, bool refreshBeforeJump, const QRectF& highlight, bool quiet)
481{
482    const QFileInfo fileInfo(filePath);
483
484    for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
485    {
486        if(tab(index)->fileInfo() == fileInfo)
487        {
488            m_tabWidget->setCurrentIndex(index);
489
490            if(refreshBeforeJump)
491            {
492                if(!currentTab()->refresh())
493                {
494                    return false;
495                }
496            }
497
498            currentTab()->jumpToPage(page);
499            currentTab()->setFocus();
500
501            if(!highlight.isNull())
502            {
503                currentTab()->temporaryHighlight(page, highlight);
504            }
505
506            return true;
507        }
508    }
509
510    return openInNewTab(filePath, page, highlight, quiet);
511}
512
513void MainWindow::startSearch(const QString& text)
514{
515    if(m_tabWidget->currentIndex() != -1)
516    {
517        m_searchDock->setVisible(true);
518
519        m_searchLineEdit->setText(text);
520        m_searchLineEdit->startSearch();
521
522        currentTab()->setFocus();
523    }
524}
525
526void MainWindow::on_tabWidget_currentChanged(int index)
527{
528    const bool hasCurrent = index != -1;
529
530    m_openCopyInNewTabAction->setEnabled(hasCurrent);
531    m_openContainingFolderAction->setEnabled(hasCurrent);
532    m_refreshAction->setEnabled(hasCurrent);
533    m_printAction->setEnabled(hasCurrent);
534    m_verify_signature->setEnabled(hasCurrent);
535    //m_detailsSignatureDock->setEnabled(hasCurrent);
536
537    m_previousPageAction->setEnabled(hasCurrent);
538    m_nextPageAction->setEnabled(hasCurrent);
539    m_firstPageAction->setEnabled(hasCurrent);
540    m_lastPageAction->setEnabled(hasCurrent);
541
542    m_setFirstPageAction->setEnabled(hasCurrent);
543
544    m_jumpToPageAction->setEnabled(hasCurrent);
545
546    m_searchAction->setEnabled(hasCurrent);
547
548    m_copyToClipboardModeAction->setEnabled(hasCurrent);
549    m_addAnnotationModeAction->setEnabled(hasCurrent);
550
551    m_continuousModeAction->setEnabled(hasCurrent);
552    m_twoPagesModeAction->setEnabled(hasCurrent);
553    m_twoPagesWithCoverPageModeAction->setEnabled(hasCurrent);
554    m_multiplePagesModeAction->setEnabled(hasCurrent);
555    m_rightToLeftModeAction->setEnabled(hasCurrent);
556
557    m_zoomInAction->setEnabled(hasCurrent);
558    m_zoomOutAction->setEnabled(hasCurrent);
559    m_originalSizeAction->setEnabled(hasCurrent);
560    m_fitToPageWidthModeAction->setEnabled(hasCurrent);
561    m_fitToPageSizeModeAction->setEnabled(hasCurrent);
562
563    m_rotateLeftAction->setEnabled(hasCurrent);
564    m_rotateRightAction->setEnabled(hasCurrent);
565
566    m_invertColorsAction->setEnabled(hasCurrent);
567    m_convertToGrayscaleAction->setEnabled(hasCurrent);
568    m_trimMarginsAction->setEnabled(hasCurrent);
569
570    m_compositionModeMenu->setEnabled(hasCurrent);
571    m_darkenWithPaperColorAction->setEnabled(hasCurrent);
572    m_lightenWithPaperColorAction->setEnabled(hasCurrent);
573
574    m_fontsAction->setEnabled(hasCurrent);
575
576    m_presentationAction->setEnabled(hasCurrent);
577
578    m_previousTabAction->setEnabled(hasCurrent);
579    m_nextTabAction->setEnabled(hasCurrent);
580    m_closeTabAction->setEnabled(hasCurrent);
581    m_closeAllTabsAction->setEnabled(hasCurrent);
582    m_closeAllTabsButCurrentTabAction->setEnabled(hasCurrent);
583
584    m_previousBookmarkAction->setEnabled(hasCurrent);
585    m_nextBookmarkAction->setEnabled(hasCurrent);
586    m_addBookmarkAction->setEnabled(hasCurrent);
587    m_removeBookmarkAction->setEnabled(hasCurrent);
588
589    m_currentPageSpinBox->setEnabled(hasCurrent);
590    m_scaleFactorComboBox->setEnabled(hasCurrent);
591    m_searchLineEdit->setEnabled(hasCurrent);
592    m_matchCaseCheckBox->setEnabled(hasCurrent);
593    m_wholeWordsCheckBox->setEnabled(hasCurrent);
594    m_highlightAllCheckBox->setEnabled(hasCurrent);
595
596    m_searchDock->toggleViewAction()->setEnabled(hasCurrent);
597
598    if(hasCurrent)
599    {
600        qDebug("if(hasCurrent)");
601        m_saveCopyAction->setEnabled(currentTab()->canSave());
602        m_saveAsAction->setEnabled(currentTab()->canSave());
603
604        if(m_searchDock->isVisible())
605        {
606            m_searchLineEdit->stopTimer();
607            m_searchLineEdit->setProgress(currentTab()->searchProgress());
608        }
609
610        m_outlineView->setModel(currentTab()->outlineModel());
611        m_propertiesView->setModel(currentTab()->propertiesModel());
612        m_bookmarksView->setModel(bookmarkModelForCurrentTab());
613        m_detailsSignatureView->setModel(view_table_verify_signature());
614
615
616        m_thumbnailsView->setScene(currentTab()->thumbnailsScene());
617        currentTab()->setThumbnailsViewportSize(m_thumbnailsView->viewport()->size());
618
619        on_currentTab_documentChanged();
620
621        on_currentTab_numberOfPagesChaned(currentTab()->numberOfPages());
622        on_currentTab_currentPageChanged(currentTab()->currentPage());
623
624        on_currentTab_canJumpChanged(currentTab()->canJumpBackward(), currentTab()->canJumpForward());
625
626        on_currentTab_continuousModeChanged(currentTab()->continuousMode());
627        on_currentTab_layoutModeChanged(currentTab()->layoutMode());
628        on_currentTab_rightToLeftModeChanged(currentTab()->rightToLeftMode());
629        on_currentTab_scaleModeChanged(currentTab()->scaleMode());
630        on_currentTab_scaleFactorChanged(currentTab()->scaleFactor());
631
632        on_currentTab_invertColorsChanged(currentTab()->invertColors());
633        on_currentTab_convertToGrayscaleChanged(currentTab()->convertToGrayscale());
634        on_currentTab_trimMarginsChanged(currentTab()->trimMargins());
635
636        on_currentTab_compositionModeChanged(currentTab()->compositionMode());
637
638        on_currentTab_highlightAllChanged(currentTab()->highlightAll());
639        on_currentTab_rubberBandModeChanged(currentTab()->rubberBandMode());
640    }
641    else
642    {
643        m_saveCopyAction->setEnabled(false);
644        m_saveAsAction->setEnabled(false);
645
646        if(m_searchDock->isVisible())
647        {
648            m_searchLineEdit->stopTimer();
649            m_searchLineEdit->setProgress(0);
650
651            m_searchDock->setVisible(false);
652        }
653
654        m_outlineView->setModel(0);
655        m_propertiesView->setModel(0);
656        m_bookmarksView->setModel(0);
657
658        m_thumbnailsView->setScene(0);
659
660        setWindowTitleForCurrentTab();
661        setCurrentPageSuffixForCurrentTab();
662
663        m_currentPageSpinBox->setValue(1);
664        m_scaleFactorComboBox->setCurrentIndex(4);
665
666        m_jumpBackwardAction->setEnabled(false);
667        m_jumpForwardAction->setEnabled(false);
668
669        m_copyToClipboardModeAction->setChecked(false);
670        m_addAnnotationModeAction->setChecked(false);
671
672        m_continuousModeAction->setChecked(false);
673        m_twoPagesModeAction->setChecked(false);
674        m_twoPagesWithCoverPageModeAction->setChecked(false);
675        m_multiplePagesModeAction->setChecked(false);
676
677        m_fitToPageSizeModeAction->setChecked(false);
678        m_fitToPageWidthModeAction->setChecked(false);
679
680        m_invertColorsAction->setChecked(false);
681        m_convertToGrayscaleAction->setChecked(false);
682        m_trimMarginsAction->setChecked(false);
683
684        m_darkenWithPaperColorAction->setChecked(false);
685        m_lightenWithPaperColorAction->setChecked(false);
686    }
687}
688
689void MainWindow::on_tabWidget_tabCloseRequested(int index)
690{
691    if(saveModifications(tab(index)))
692    {
693        closeTab(tab(index));
694    }
695}
696
697void MainWindow::on_tabWidget_tabContextMenuRequested(const QPoint& globalPos, int index)
698{
699    QMenu menu;
700
701    // We block their signals since we need to handle them using the selected instead of the current tab.
702    SignalBlocker openCopyInNewTabSignalBlocker(m_openCopyInNewTabAction);
703    SignalBlocker openContainingFolderSignalBlocker(m_openContainingFolderAction);
704
705    QAction* copyFilePathAction = createTemporaryAction(&menu, tr("Copy file path"), QLatin1String("copyFilePath"));
706    QAction* selectFilePathAction = createTemporaryAction(&menu, tr("Select file path"), QLatin1String("selectFilePath"));
707
708    QAction* closeAllTabsAction = createTemporaryAction(&menu, tr("Close all tabs"), QLatin1String("closeAllTabs"));
709    QAction* closeAllTabsButThisOneAction = createTemporaryAction(&menu, tr("Close all tabs but this one"), QLatin1String("closeAllTabsButThisOne"));
710    QAction* closeAllTabsToTheLeftAction = createTemporaryAction(&menu, tr("Close all tabs to the left"), QLatin1String("closeAllTabsToTheLeft"));
711    QAction* closeAllTabsToTheRightAction = createTemporaryAction(&menu, tr("Close all tabs to the right"), QLatin1String("closeAllTabsToTheRight"));
712
713    selectFilePathAction->setVisible(QApplication::clipboard()->supportsSelection());
714
715    QList< QAction* > actions;
716
717    actions << m_openCopyInNewTabAction << m_openContainingFolderAction
718            << copyFilePathAction << selectFilePathAction
719            << closeAllTabsAction << closeAllTabsButThisOneAction
720            << closeAllTabsToTheLeftAction << closeAllTabsToTheRightAction;
721
722    addWidgetActions(&menu, s_settings->mainWindow().tabContextMenu(), actions);
723
724    const QAction* action = menu.exec(globalPos);
725
726    const DocumentView* selectedTab = tab(index);
727    QList< DocumentView* > tabsToClose;
728
729    if(action == m_openCopyInNewTabAction)
730    {
731        openInNewTab(selectedTab->fileInfo().filePath(), selectedTab->currentPage());
732
733        return;
734    }
735    else if(action == m_openContainingFolderAction)
736    {
737        QDesktopServices::openUrl(QUrl::fromLocalFile(selectedTab->fileInfo().absolutePath()));
738
739        return;
740    }
741    else if(action == copyFilePathAction)
742    {
743        QApplication::clipboard()->setText(selectedTab->fileInfo().absoluteFilePath());
744
745        return;
746    }
747    else if(action == selectFilePathAction)
748    {
749        QApplication::clipboard()->setText(selectedTab->fileInfo().absoluteFilePath(), QClipboard::Selection);
750
751        return;
752    }
753    else if(action == closeAllTabsAction)
754    {
755        tabsToClose = tabs();
756    }
757    else if(action == closeAllTabsButThisOneAction)
758    {
759        const int count = m_tabWidget->count();
760
761        for(int indexToClose = 0; indexToClose < count; ++indexToClose)
762        {
763            if(indexToClose != index)
764            {
765                tabsToClose.append(tab(indexToClose));
766            }
767        }
768    }
769    else if(action == closeAllTabsToTheLeftAction)
770    {
771        for(int indexToClose = 0; indexToClose < index; ++indexToClose)
772        {
773            tabsToClose.append(tab(indexToClose));
774        }
775    }
776    else if(action == closeAllTabsToTheRightAction)
777    {
778        const int count = m_tabWidget->count();
779
780        for(int indexToClose = count - 1; indexToClose > index; --indexToClose)
781        {
782            tabsToClose.append(tab(indexToClose));
783        }
784    }
785    else
786    {
787        return;
788    }
789
790    disconnectCurrentTabChanged();
791
792    foreach(DocumentView* tab, tabsToClose)
793    {
794        if(saveModifications(tab))
795        {
796            closeTab(tab);
797        }
798    }
799
800    reconnectCurrentTabChanged();
801}
802
803#define ONLY_IF_SENDER_IS_CURRENT_TAB if(!senderIsCurrentTab()) { return; }
804
805void MainWindow::on_currentTab_documentChanged()
806{
807    for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
808    {
809        if(sender() == m_tabWidget->widget(index))
810        {
811            m_tabWidget->setTabText(index, tab(index)->title());
812            m_tabWidget->setTabToolTip(index, tab(index)->fileInfo().absoluteFilePath());
813
814            foreach(QAction* tabAction, m_tabsMenu->actions())
815            {
816                if(tabAction->parent() == m_tabWidget->widget(index))
817                {
818                    tabAction->setText(m_tabWidget->tabText(index));
819
820                    break;
821                }
822            }
823
824            break;
825        }
826    }
827
828    ONLY_IF_SENDER_IS_CURRENT_TAB
829
830    m_outlineView->restoreExpansion();
831
832    setWindowTitleForCurrentTab();
833
834    setWindowModified(currentTab() != 0 ? currentTab()->wasModified() : false);
835}
836
837void MainWindow::on_currentTab_documentModified()
838{
839    ONLY_IF_SENDER_IS_CURRENT_TAB
840
841    setWindowModified(true);
842}
843
844void MainWindow::on_currentTab_numberOfPagesChaned(int numberOfPages)
845{
846    ONLY_IF_SENDER_IS_CURRENT_TAB
847
848    m_currentPageSpinBox->setRange(1, numberOfPages);
849
850    setWindowTitleForCurrentTab();
851    setCurrentPageSuffixForCurrentTab();
852}
853
854void MainWindow::on_currentTab_currentPageChanged(int currentPage)
855{
856    scheduleSaveTabs();
857    scheduleSavePerFileSettings();
858
859    ONLY_IF_SENDER_IS_CURRENT_TAB
860
861    m_currentPageSpinBox->setValue(currentPage);
862
863    if(s_settings->mainWindow().synchronizeOutlineView() && m_outlineView->model() != 0)
864    {
865        const QModelIndex match = synchronizeOutlineView(currentPage, m_outlineView->model(), QModelIndex());
866
867        if(match.isValid())
868        {
869            m_outlineView->collapseAll();
870
871            m_outlineView->expandAbove(match);
872            m_outlineView->setCurrentIndex(match);
873        }
874    }
875
876    m_thumbnailsView->ensureVisible(currentTab()->thumbnailItems().at(currentPage - 1));
877
878    setWindowTitleForCurrentTab();
879    setCurrentPageSuffixForCurrentTab();
880}
881
882void MainWindow::on_currentTab_canJumpChanged(bool backward, bool forward)
883{
884    ONLY_IF_SENDER_IS_CURRENT_TAB
885
886    m_jumpBackwardAction->setEnabled(backward);
887    m_jumpForwardAction->setEnabled(forward);
888}
889
890void MainWindow::on_currentTab_continuousModeChanged(bool continuousMode)
891{
892    scheduleSaveTabs();
893    scheduleSavePerFileSettings();
894
895    ONLY_IF_SENDER_IS_CURRENT_TAB
896
897    m_continuousModeAction->setChecked(continuousMode);
898}
899
900void MainWindow::on_currentTab_layoutModeChanged(LayoutMode layoutMode)
901{
902    scheduleSaveTabs();
903    scheduleSavePerFileSettings();
904
905    ONLY_IF_SENDER_IS_CURRENT_TAB
906
907    m_twoPagesModeAction->setChecked(layoutMode == TwoPagesMode);
908    m_twoPagesWithCoverPageModeAction->setChecked(layoutMode == TwoPagesWithCoverPageMode);
909    m_multiplePagesModeAction->setChecked(layoutMode == MultiplePagesMode);
910}
911
912void MainWindow::on_currentTab_rightToLeftModeChanged(bool rightToLeftMode)
913{
914    scheduleSaveTabs();
915    scheduleSavePerFileSettings();
916
917    ONLY_IF_SENDER_IS_CURRENT_TAB
918
919    m_rightToLeftModeAction->setChecked(rightToLeftMode);
920}
921
922void MainWindow::on_currentTab_scaleModeChanged(ScaleMode scaleMode)
923{
924    scheduleSaveTabs();
925    scheduleSavePerFileSettings();
926
927    ONLY_IF_SENDER_IS_CURRENT_TAB
928
929    switch(scaleMode)
930    {
931    default:
932    case ScaleFactorMode:
933        m_fitToPageWidthModeAction->setChecked(false);
934        m_fitToPageSizeModeAction->setChecked(false);
935
936        on_currentTab_scaleFactorChanged(currentTab()->scaleFactor());
937        break;
938    case FitToPageWidthMode:
939        m_fitToPageWidthModeAction->setChecked(true);
940        m_fitToPageSizeModeAction->setChecked(false);
941
942        m_scaleFactorComboBox->setCurrentIndex(0);
943
944        m_zoomInAction->setEnabled(true);
945        m_zoomOutAction->setEnabled(true);
946        break;
947    case FitToPageSizeMode:
948        m_fitToPageWidthModeAction->setChecked(false);
949        m_fitToPageSizeModeAction->setChecked(true);
950
951        m_scaleFactorComboBox->setCurrentIndex(1);
952
953        m_zoomInAction->setEnabled(true);
954        m_zoomOutAction->setEnabled(true);
955        break;
956    }
957}
958
959void MainWindow::on_currentTab_scaleFactorChanged(qreal scaleFactor)
960{
961    if(senderIsCurrentTab())
962    {
963        if(currentTab()->scaleMode() == ScaleFactorMode)
964        {
965            m_scaleFactorComboBox->setCurrentIndex(m_scaleFactorComboBox->findData(scaleFactor));
966            m_scaleFactorComboBox->lineEdit()->setText(QString("%1 %").arg(qRound(scaleFactor * 100.0)));
967
968            m_zoomInAction->setDisabled(qFuzzyCompare(scaleFactor, s_settings->documentView().maximumScaleFactor()));
969            m_zoomOutAction->setDisabled(qFuzzyCompare(scaleFactor, s_settings->documentView().minimumScaleFactor()));
970        }
971
972        scheduleSaveTabs();
973        scheduleSavePerFileSettings();
974    }
975}
976
977void MainWindow::on_currentTab_rotationChanged(Rotation rotation)
978{
979    Q_UNUSED(rotation);
980
981    if(senderIsCurrentTab())
982    {
983        scheduleSaveTabs();
984        scheduleSavePerFileSettings();
985    }
986}
987
988void MainWindow::on_currentTab_linkClicked(int page)
989{
990    openInNewTab(currentTab()->fileInfo().filePath(), page);
991}
992
993void MainWindow::on_currentTab_linkClicked(bool newTab, const QString& filePath, int page)
994{
995    if(newTab)
996    {
997        openInNewTab(filePath, page);
998    }
999    else
1000    {
1001        jumpToPageOrOpenInNewTab(filePath, page, true);
1002    }
1003}
1004
1005void MainWindow::on_currentTab_renderFlagsChanged(qpdfview::RenderFlags renderFlags)
1006{
1007    Q_UNUSED(renderFlags);
1008
1009    scheduleSaveTabs();
1010    scheduleSavePerFileSettings();
1011}
1012
1013void MainWindow::on_currentTab_invertColorsChanged(bool invertColors)
1014{
1015    ONLY_IF_SENDER_IS_CURRENT_TAB
1016
1017    m_invertColorsAction->setChecked(invertColors);
1018}
1019
1020void MainWindow::on_currentTab_convertToGrayscaleChanged(bool convertToGrayscale)
1021{
1022    ONLY_IF_SENDER_IS_CURRENT_TAB
1023
1024    m_convertToGrayscaleAction->setChecked(convertToGrayscale);
1025}
1026
1027void MainWindow::on_currentTab_trimMarginsChanged(bool trimMargins)
1028{
1029    ONLY_IF_SENDER_IS_CURRENT_TAB
1030
1031    m_trimMarginsAction->setChecked(trimMargins);
1032}
1033
1034void MainWindow::on_currentTab_compositionModeChanged(CompositionMode compositionMode)
1035{
1036    ONLY_IF_SENDER_IS_CURRENT_TAB
1037
1038    switch(compositionMode)
1039    {
1040    default:
1041    case DefaultCompositionMode:
1042        m_darkenWithPaperColorAction->setChecked(false);
1043        m_lightenWithPaperColorAction->setChecked(false);
1044        break;
1045    case DarkenWithPaperColorMode:
1046        m_darkenWithPaperColorAction->setChecked(true);
1047        m_lightenWithPaperColorAction->setChecked(false);
1048        break;
1049    case LightenWithPaperColorMode:
1050        m_darkenWithPaperColorAction->setChecked(false);
1051        m_lightenWithPaperColorAction->setChecked(true);
1052        break;
1053    }
1054}
1055
1056void MainWindow::on_currentTab_highlightAllChanged(bool highlightAll)
1057{
1058    ONLY_IF_SENDER_IS_CURRENT_TAB
1059
1060    m_highlightAllCheckBox->setChecked(highlightAll);
1061}
1062
1063void MainWindow::on_currentTab_rubberBandModeChanged(RubberBandMode rubberBandMode)
1064{
1065    ONLY_IF_SENDER_IS_CURRENT_TAB
1066
1067    m_copyToClipboardModeAction->setChecked(rubberBandMode == CopyToClipboardMode);
1068    m_addAnnotationModeAction->setChecked(rubberBandMode == AddAnnotationMode);
1069}
1070
1071void MainWindow::on_currentTab_searchFinished()
1072{
1073    ONLY_IF_SENDER_IS_CURRENT_TAB
1074
1075    m_searchLineEdit->setProgress(0);
1076}
1077
1078void MainWindow::on_currentTab_searchProgressChanged(int progress)
1079{
1080    ONLY_IF_SENDER_IS_CURRENT_TAB
1081
1082    m_searchLineEdit->setProgress(progress);
1083}
1084
1085void MainWindow::on_currentTab_customContextMenuRequested(const QPoint& pos)
1086{
1087    ONLY_IF_SENDER_IS_CURRENT_TAB
1088
1089    QMenu menu;
1090
1091    QAction* sourceLinkAction = sourceLinkActionForCurrentTab(&menu, pos);
1092
1093    QList< QAction* > actions;
1094
1095    actions << m_openCopyInNewTabAction << m_openContainingFolderAction
1096            << m_previousPageAction << m_nextPageAction
1097            << m_firstPageAction << m_lastPageAction
1098            << m_jumpToPageAction << m_jumpBackwardAction << m_jumpForwardAction
1099            << m_setFirstPageAction;
1100
1101    if(m_searchDock->isVisible())
1102    {
1103        actions << m_findPreviousAction << m_findNextAction << m_cancelSearchAction;
1104    }
1105
1106    menu.addAction(sourceLinkAction);
1107    menu.addSeparator();
1108
1109    addWidgetActions(&menu, s_settings->mainWindow().documentContextMenu(), actions);
1110
1111    const QAction* action = menu.exec(currentTab()->mapToGlobal(pos));
1112
1113    if(action == sourceLinkAction)
1114    {
1115        currentTab()->openInSourceEditor(sourceLinkAction->data().value< DocumentView::SourceLink >());
1116    }
1117}
1118
1119#undef ONLY_IF_SENDER_IS_CURRENT_TAB
1120
1121void MainWindow::on_currentPage_editingFinished()
1122{
1123    if(m_tabWidget->currentIndex() != -1)
1124    {
1125        currentTab()->jumpToPage(m_currentPageSpinBox->value());
1126    }
1127}
1128
1129void MainWindow::on_currentPage_returnPressed()
1130{
1131    currentTab()->setFocus();
1132}
1133
1134void MainWindow::on_scaleFactor_activated(int index)
1135{
1136    if(index == 0)
1137    {
1138        currentTab()->setScaleMode(FitToPageWidthMode);
1139    }
1140    else if(index == 1)
1141    {
1142        currentTab()->setScaleMode(FitToPageSizeMode);
1143    }
1144    else
1145    {
1146        bool ok = false;
1147        const qreal scaleFactor = m_scaleFactorComboBox->itemData(index).toReal(&ok);
1148
1149        if(ok)
1150        {
1151            currentTab()->setScaleFactor(scaleFactor);
1152            currentTab()->setScaleMode(ScaleFactorMode);
1153        }
1154    }
1155
1156    currentTab()->setFocus();
1157}
1158
1159void MainWindow::on_scaleFactor_editingFinished()
1160{
1161    if(m_tabWidget->currentIndex() != -1)
1162    {
1163        bool ok = false;
1164        qreal scaleFactor = m_scaleFactorComboBox->lineEdit()->text().toInt(&ok) / 100.0;
1165
1166        scaleFactor = qMax(scaleFactor, s_settings->documentView().minimumScaleFactor());
1167        scaleFactor = qMin(scaleFactor, s_settings->documentView().maximumScaleFactor());
1168
1169        if(ok)
1170        {
1171            currentTab()->setScaleFactor(scaleFactor);
1172            currentTab()->setScaleMode(ScaleFactorMode);
1173        }
1174
1175        on_currentTab_scaleFactorChanged(currentTab()->scaleFactor());
1176        on_currentTab_scaleModeChanged(currentTab()->scaleMode());
1177    }
1178}
1179
1180void MainWindow::on_scaleFactor_returnPressed()
1181{
1182    currentTab()->setFocus();
1183}
1184
1185void MainWindow::on_open_triggered()
1186{
1187    if(m_tabWidget->currentIndex() != -1)
1188    {
1189        const QString path = s_settings->mainWindow().openPath();
1190        const QString filePath = QFileDialog::getOpenFileName(this, tr("Open"), path, DocumentView::openFilter().join(";;"));
1191
1192        if(!filePath.isEmpty())
1193        {
1194            open(filePath);
1195        }
1196    }
1197    else
1198    {
1199        on_openInNewTab_triggered();
1200    }
1201}
1202
1203void MainWindow::on_openInNewTab_triggered()
1204{
1205    const QString path = s_settings->mainWindow().openPath();
1206    const QStringList filePaths = QFileDialog::getOpenFileNames(this, tr("Open in new tab"), path, DocumentView::openFilter().join(";;"));
1207
1208    if(!filePaths.isEmpty())
1209    {
1210        disconnectCurrentTabChanged();
1211
1212        foreach(const QString& filePath, filePaths)
1213        {
1214            openInNewTab(filePath);
1215        }
1216
1217        reconnectCurrentTabChanged();
1218    }
1219}
1220
1221void MainWindow::on_openCopyInNewTab_triggered()
1222{
1223    openInNewTab(currentTab()->fileInfo().filePath(), currentTab()->currentPage());
1224}
1225
1226void MainWindow::on_openContainingFolder_triggered()
1227{
1228    QDesktopServices::openUrl(QUrl::fromLocalFile(currentTab()->fileInfo().absolutePath()));
1229}
1230
1231void MainWindow::on_refresh_triggered()
1232{
1233    if(!currentTab()->refresh())
1234    {
1235        QMessageBox::warning(this, tr("Warning"), tr("Could not refresh '%1'.").arg(currentTab()->fileInfo().filePath()));
1236    }
1237}
1238
1239void MainWindow::on_saveCopy_triggered()
1240{
1241    const QDir dir = QDir(s_settings->mainWindow().savePath());
1242    const QString filePath = QFileDialog::getSaveFileName(this, tr("Save copy"), dir.filePath(currentTab()->fileInfo().fileName()), currentTab()->saveFilter().join(";;"));
1243
1244    if(!filePath.isEmpty())
1245    {
1246        if(currentTab()->save(filePath, false))
1247        {
1248            s_settings->mainWindow().setSavePath(QFileInfo(filePath).absolutePath());
1249        }
1250        else
1251        {
1252            QMessageBox::warning(this, tr("Warning"), tr("Could not save copy at '%1'.").arg(filePath));
1253        }
1254    }
1255}
1256
1257void MainWindow::on_saveAs_triggered()
1258{
1259    const QString filePath = QFileDialog::getSaveFileName(this, tr("Save as"), currentTab()->fileInfo().filePath(), currentTab()->saveFilter().join(";;"));
1260
1261    if(!filePath.isEmpty())
1262    {
1263        if(currentTab()->save(filePath, true))
1264        {
1265            open(filePath, currentTab()->currentPage());
1266        }
1267        else
1268        {
1269            QMessageBox::warning(this, tr("Warning"), tr("Could not save as '%1'.").arg(filePath));
1270        }
1271    }
1272}
1273
1274void MainWindow::on_print_triggered()
1275{
1276    QScopedPointer< QPrinter > printer(PrintDialog::createPrinter());
1277    QScopedPointer< PrintDialog > printDialog(new PrintDialog(printer.data(), this));
1278
1279    printer->setDocName(currentTab()->fileInfo().completeBaseName());
1280    printer->setFullPage(true);
1281
1282    printDialog->setMinMax(1, currentTab()->numberOfPages());
1283    printDialog->setOption(QPrintDialog::PrintToFile, false);
1284
1285#if QT_VERSION >= QT_VERSION_CHECK(4,7,0)
1286
1287    printDialog->setOption(QPrintDialog::PrintCurrentPage, true);
1288
1289#endif // QT_VERSION
1290
1291    if(printDialog->exec() != QDialog::Accepted)
1292    {
1293        return;
1294    }
1295
1296#if QT_VERSION >= QT_VERSION_CHECK(4,7,0)
1297
1298    if(printDialog->printRange() == QPrintDialog::CurrentPage)
1299    {
1300        printer->setFromTo(currentTab()->currentPage(), currentTab()->currentPage());
1301    }
1302
1303#endif // QT_VERSION
1304
1305    if(!currentTab()->print(printer.data(), printDialog->printOptions()))
1306    {
1307        QMessageBox::warning(this, tr("Warning"), tr("Could not print '%1'.").arg(currentTab()->fileInfo().filePath()));
1308    }
1309}
1310
1311void MainWindow::on_recentlyUsed_openTriggered(const QString& filePath)
1312{
1313    if(!jumpToPageOrOpenInNewTab(filePath, -1, true))
1314    {
1315        m_recentlyUsedMenu->removeOpenAction(filePath);
1316    }
1317}
1318
1319void MainWindow::on_previousPage_triggered()
1320{
1321    currentTab()->previousPage();
1322}
1323
1324void MainWindow::on_nextPage_triggered()
1325{
1326    currentTab()->nextPage();
1327}
1328
1329void MainWindow::on_firstPage_triggered()
1330{
1331    currentTab()->firstPage();
1332}
1333
1334void MainWindow::on_lastPage_triggered()
1335{
1336    currentTab()->lastPage();
1337}
1338
1339void MainWindow::on_setFirstPage_triggered()
1340{
1341    bool ok = false;
1342    const int pageNumber = getMappedNumber(new TextValueMapper(this),
1343                                           this, tr("Set first page"), tr("Select the first page of the body matter:"),
1344                                           currentTab()->currentPage(), 1, currentTab()->numberOfPages(), &ok);
1345
1346    if(ok)
1347    {
1348        currentTab()->setFirstPage(pageNumber);
1349    }
1350}
1351
1352void MainWindow::on_jumpToPage_triggered()
1353{
1354    bool ok = false;
1355    const int pageNumber = getMappedNumber(new TextValueMapper(this),
1356                                           this, tr("Jump to page"), tr("Page:"),
1357                                           currentTab()->currentPage(), 1, currentTab()->numberOfPages(), &ok);
1358
1359    if(ok)
1360    {
1361        currentTab()->jumpToPage(pageNumber);
1362    }
1363}
1364
1365void MainWindow::on_jumpBackward_triggered()
1366{
1367    currentTab()->jumpBackward();
1368}
1369
1370void MainWindow::on_jumpForward_triggered()
1371{
1372    currentTab()->jumpForward();
1373}
1374
1375void MainWindow::on_search_triggered()
1376{
1377    m_searchDock->setVisible(true);
1378    m_searchDock->raise();
1379
1380    m_searchLineEdit->selectAll();
1381    m_searchLineEdit->setFocus();
1382}
1383
1384void MainWindow::on_findPrevious_triggered()
1385{
1386    if(!m_searchLineEdit->text().isEmpty())
1387    {
1388        currentTab()->findPrevious();
1389    }
1390}
1391
1392void MainWindow::on_findNext_triggered()
1393{
1394    if(!m_searchLineEdit->text().isEmpty())
1395    {
1396        currentTab()->findNext();
1397    }
1398}
1399
1400void MainWindow::on_cancelSearch_triggered()
1401{
1402    m_searchLineEdit->stopTimer();
1403    m_searchLineEdit->setProgress(0);
1404
1405    for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
1406    {
1407        tab(index)->cancelSearch();
1408    }
1409
1410    if(!s_settings->mainWindow().extendedSearchDock())
1411    {
1412        m_searchDock->setVisible(false);
1413    }
1414}
1415
1416void MainWindow::on_copyToClipboardMode_triggered(bool checked)
1417{
1418    currentTab()->setRubberBandMode(checked ? CopyToClipboardMode : ModifiersMode);
1419}
1420
1421void MainWindow::on_addAnnotationMode_triggered(bool checked)
1422{
1423    currentTab()->setRubberBandMode(checked ? AddAnnotationMode : ModifiersMode);
1424}
1425
1426void MainWindow::on_settings_triggered()
1427{
1428    QScopedPointer< SettingsDialog > settingsDialog(new SettingsDialog(this));
1429
1430    if(settingsDialog->exec() != QDialog::Accepted)
1431    {
1432        return;
1433    }
1434
1435    s_settings->sync();
1436
1437    m_tabWidget->setTabPosition(static_cast< QTabWidget::TabPosition >(s_settings->mainWindow().tabPosition()));
1438    m_tabWidget->setTabBarPolicy(static_cast< TabWidget::TabBarPolicy >(s_settings->mainWindow().tabVisibility()));
1439    m_tabWidget->setSpreadTabs(s_settings->mainWindow().spreadTabs());
1440
1441    m_tabsMenu->setSearchable(s_settings->mainWindow().searchableMenus());
1442    m_bookmarksMenu->setSearchable(s_settings->mainWindow().searchableMenus());
1443
1444    m_saveDatabaseTimer->setInterval(s_settings->mainWindow().saveDatabaseInterval());
1445
1446    for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
1447    {
1448        if(!tab(index)->refresh())
1449        {
1450            QMessageBox::warning(this, tr("Warning"), tr("Could not refresh '%1'.").arg(currentTab()->fileInfo().filePath()));
1451        }
1452    }
1453}
1454
1455void MainWindow::on_continuousMode_triggered(bool checked)
1456{
1457    currentTab()->setContinuousMode(checked);
1458}
1459
1460void MainWindow::on_twoPagesMode_triggered(bool checked)
1461{
1462    currentTab()->setLayoutMode(checked ? TwoPagesMode : SinglePageMode);
1463}
1464
1465void MainWindow::on_twoPagesWithCoverPageMode_triggered(bool checked)
1466{
1467    currentTab()->setLayoutMode(checked ? TwoPagesWithCoverPageMode : SinglePageMode);
1468}
1469
1470void MainWindow::on_multiplePagesMode_triggered(bool checked)
1471{
1472    currentTab()->setLayoutMode(checked ? MultiplePagesMode : SinglePageMode);
1473}
1474
1475void MainWindow::on_rightToLeftMode_triggered(bool checked)
1476{
1477    currentTab()->setRightToLeftMode(checked);
1478}
1479
1480void MainWindow::on_zoomIn_triggered()
1481{
1482    currentTab()->zoomIn();
1483}
1484
1485void MainWindow::on_zoomOut_triggered()
1486{
1487    currentTab()->zoomOut();
1488}
1489
1490void MainWindow::on_originalSize_triggered()
1491{
1492    currentTab()->originalSize();
1493}
1494
1495void MainWindow::on_fitToPageWidthMode_triggered(bool checked)
1496{
1497    currentTab()->setScaleMode(checked ? FitToPageWidthMode : ScaleFactorMode);
1498}
1499
1500void MainWindow::on_fitToPageSizeMode_triggered(bool checked)
1501{
1502    currentTab()->setScaleMode(checked ? FitToPageSizeMode : ScaleFactorMode);
1503}
1504
1505void MainWindow::on_rotateLeft_triggered()
1506{
1507    currentTab()->rotateLeft();
1508}
1509
1510void MainWindow::on_rotateRight_triggered()
1511{
1512    currentTab()->rotateRight();
1513}
1514
1515void MainWindow::on_invertColors_triggered(bool checked)
1516{
1517    currentTab()->setInvertColors(checked);
1518}
1519
1520void MainWindow::on_convertToGrayscale_triggered(bool checked)
1521{
1522    currentTab()->setConvertToGrayscale(checked);
1523}
1524
1525void MainWindow::on_trimMargins_triggered(bool checked)
1526{
1527    currentTab()->setTrimMargins(checked);
1528}
1529
1530void MainWindow::on_darkenWithPaperColor_triggered(bool checked)
1531{
1532    currentTab()->setCompositionMode(checked ? DarkenWithPaperColorMode : DefaultCompositionMode);
1533}
1534
1535void MainWindow::on_lightenWithPaperColor_triggered(bool checked)
1536{
1537    currentTab()->setCompositionMode(checked ? LightenWithPaperColorMode : DefaultCompositionMode);
1538}
1539
1540void MainWindow::on_fonts_triggered()
1541{
1542    QScopedPointer< QStandardItemModel > fontsModel(currentTab()->fontsModel());
1543    QScopedPointer< FontsDialog > dialog(new FontsDialog(fontsModel.data(), this));
1544
1545    dialog->exec();
1546}
1547
1548void MainWindow::on_fullscreen_triggered(bool checked)
1549{
1550    if(checked)
1551    {
1552        m_fullscreenAction->setData(saveGeometry());
1553
1554        showFullScreen();
1555    }
1556    else
1557    {
1558        restoreGeometry(m_fullscreenAction->data().toByteArray());
1559
1560        showNormal();
1561
1562        restoreGeometry(m_fullscreenAction->data().toByteArray());
1563    }
1564
1565    if(s_settings->mainWindow().toggleToolAndMenuBarsWithFullscreen())
1566    {
1567        m_toggleToolBarsAction->trigger();
1568        m_toggleMenuBarAction->trigger();
1569    }
1570}
1571
1572void MainWindow::on_presentation_triggered()
1573{
1574    currentTab()->startPresentation();
1575}
1576
1577void MainWindow::on_previousTab_triggered()
1578{
1579    if(m_tabWidget->currentIndex() > 0)
1580    {
1581        m_tabWidget->setCurrentIndex(m_tabWidget->currentIndex() - 1);
1582    }
1583    else
1584    {
1585        m_tabWidget->setCurrentIndex(m_tabWidget->count() - 1);
1586    }
1587}
1588
1589void MainWindow::on_nextTab_triggered()
1590{
1591    if(m_tabWidget->currentIndex() < m_tabWidget->count() - 1)
1592    {
1593        m_tabWidget->setCurrentIndex(m_tabWidget->currentIndex() + 1);
1594    }
1595    else
1596    {
1597        m_tabWidget->setCurrentIndex(0);
1598    }
1599}
1600
1601void MainWindow::on_closeTab_triggered()
1602{
1603    if(saveModifications(currentTab()))
1604    {
1605        closeTab(currentTab());
1606    }
1607}
1608
1609void MainWindow::on_closeAllTabs_triggered()
1610{
1611    disconnectCurrentTabChanged();
1612
1613    foreach(DocumentView* tab, tabs())
1614    {
1615        if(saveModifications(tab))
1616        {
1617            closeTab(tab);
1618        }
1619    }
1620
1621    reconnectCurrentTabChanged();
1622}
1623
1624void MainWindow::on_closeAllTabsButCurrentTab_triggered()
1625{
1626    disconnectCurrentTabChanged();
1627
1628    DocumentView* tab = currentTab();
1629
1630    const int oldIndex = m_tabWidget->currentIndex();
1631    const QString tabText = m_tabWidget->tabText(oldIndex);
1632    const QString tabToolTip = m_tabWidget->tabToolTip(oldIndex);
1633
1634    m_tabWidget->removeTab(oldIndex);
1635
1636    foreach(DocumentView* tab, tabs())
1637    {
1638        if(saveModifications(tab))
1639        {
1640            closeTab(tab);
1641        }
1642    }
1643
1644    const int newIndex = m_tabWidget->addTab(tab, tabText);
1645    m_tabWidget->setTabToolTip(newIndex, tabToolTip);
1646    m_tabWidget->setCurrentIndex(newIndex);
1647
1648    reconnectCurrentTabChanged();
1649}
1650
1651void MainWindow::on_restoreMostRecentlyClosedTab_triggered()
1652{
1653    m_recentlyClosedMenu->triggerLastTabAction();
1654}
1655
1656void MainWindow::on_recentlyClosed_tabActionTriggered(QAction* tabAction)
1657{
1658    DocumentView* tab = static_cast< DocumentView* >(tabAction->parent());
1659
1660    tab->setParent(m_tabWidget);
1661    tab->setVisible(true);
1662
1663    addTab(tab);
1664    m_tabsMenu->addAction(tabAction);
1665}
1666
1667void MainWindow::on_tabAction_triggered()
1668{
1669    for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
1670    {
1671        if(sender()->parent() == m_tabWidget->widget(index))
1672        {
1673            m_tabWidget->setCurrentIndex(index);
1674
1675            break;
1676        }
1677    }
1678}
1679
1680void MainWindow::on_tabShortcut_activated()
1681{
1682    for(int index = 0; index < 9; ++index)
1683    {
1684        if(sender() == m_tabShortcuts[index])
1685        {
1686            m_tabWidget->setCurrentIndex(index);
1687
1688            break;
1689        }
1690    }
1691}
1692
1693void MainWindow::on_previousBookmark_triggered()
1694{
1695    if(const BookmarkModel* model = bookmarkModelForCurrentTab())
1696    {
1697        QList< int > pages;
1698
1699        for(int row = 0, rowCount = model->rowCount(); row < rowCount; ++row)
1700        {
1701            pages.append(model->index(row).data(BookmarkModel::PageRole).toInt());
1702        }
1703
1704        if(!pages.isEmpty())
1705        {
1706            qSort(pages);
1707
1708            QList< int >::const_iterator lowerBound = --qLowerBound(pages, currentTab()->currentPage());
1709
1710            if(lowerBound >= pages.constBegin())
1711            {
1712                currentTab()->jumpToPage(*lowerBound);
1713            }
1714            else
1715            {
1716                currentTab()->jumpToPage(pages.last());
1717            }
1718        }
1719    }
1720}
1721
1722void MainWindow::on_nextBookmark_triggered()
1723{
1724    if(const BookmarkModel* model = bookmarkModelForCurrentTab())
1725    {
1726        QList< int > pages;
1727
1728        for(int row = 0, rowCount = model->rowCount(); row < rowCount; ++row)
1729        {
1730            pages.append(model->index(row).data(BookmarkModel::PageRole).toInt());
1731        }
1732
1733        if(!pages.isEmpty())
1734        {
1735            qSort(pages);
1736
1737            QList< int >::const_iterator upperBound = qUpperBound(pages, currentTab()->currentPage());
1738
1739            if(upperBound < pages.constEnd())
1740            {
1741                currentTab()->jumpToPage(*upperBound);
1742            }
1743            else
1744            {
1745                currentTab()->jumpToPage(pages.first());
1746            }
1747        }
1748    }
1749}
1750
1751void MainWindow::on_addBookmark_triggered()
1752{
1753    const QString& currentPageLabel = s_settings->mainWindow().usePageLabel() || currentTab()->hasFrontMatter()
1754            ? currentTab()->pageLabelFromNumber(currentTab()->currentPage())
1755            : currentTab()->defaultPageLabelFromNumber(currentTab()->currentPage());
1756
1757    BookmarkItem bookmark(currentTab()->currentPage(), tr("Jump to page %1").arg(currentPageLabel));
1758
1759    BookmarkModel* model = bookmarkModelForCurrentTab(false);
1760
1761    if(model != 0)
1762    {
1763        model->findBookmark(bookmark);
1764    }
1765
1766    QScopedPointer< BookmarkDialog > dialog(new BookmarkDialog(bookmark, this));
1767
1768    if(dialog->exec() == QDialog::Accepted)
1769    {
1770        if(model == 0)
1771        {
1772            model = bookmarkModelForCurrentTab(true);
1773
1774            m_bookmarksView->setModel(model);
1775        }
1776
1777        model->addBookmark(bookmark);
1778
1779        m_bookmarksMenuIsDirty = true;
1780        scheduleSaveBookmarks();
1781    }
1782}
1783
1784void MainWindow::on_removeBookmark_triggered()
1785{
1786    BookmarkModel* model = bookmarkModelForCurrentTab();
1787
1788    if(model != 0)
1789    {
1790        model->removeBookmark(BookmarkItem(currentTab()->currentPage()));
1791
1792        if(model->isEmpty())
1793        {
1794            m_bookmarksView->setModel(0);
1795
1796            BookmarkModel::forgetPath(currentTab()->fileInfo().absoluteFilePath());
1797        }
1798
1799        m_bookmarksMenuIsDirty = true;
1800        scheduleSaveBookmarks();
1801    }
1802}
1803
1804void MainWindow::on_removeAllBookmarks_triggered()
1805{
1806    m_bookmarksView->setModel(0);
1807
1808    BookmarkModel::forgetAllPaths();
1809
1810    m_bookmarksMenuIsDirty = true;
1811    scheduleSaveBookmarks();
1812}
1813
1814void MainWindow::on_bookmarksMenu_aboutToShow()
1815{
1816    if(!m_bookmarksMenuIsDirty)
1817    {
1818        return;
1819    }
1820
1821    m_bookmarksMenuIsDirty = false;
1822
1823
1824    m_bookmarksMenu->clear();
1825
1826    m_bookmarksMenu->addActions(QList< QAction* >() << m_previousBookmarkAction << m_nextBookmarkAction);
1827    m_bookmarksMenu->addSeparator();
1828    m_bookmarksMenu->addActions(QList< QAction* >() << m_addBookmarkAction << m_removeBookmarkAction << m_removeAllBookmarksAction);
1829    m_bookmarksMenu->addSeparator();
1830
1831    foreach(const QString& absoluteFilePath, BookmarkModel::knownPaths())
1832    {
1833        const BookmarkModel* model = BookmarkModel::fromPath(absoluteFilePath);
1834
1835        BookmarkMenu* menu = new BookmarkMenu(QFileInfo(absoluteFilePath), m_bookmarksMenu);
1836
1837        for(int row = 0, rowCount = model->rowCount(); row < rowCount; ++row)
1838        {
1839            const QModelIndex index = model->index(row);
1840
1841            menu->addJumpToPageAction(index.data(BookmarkModel::PageRole).toInt(), index.data(BookmarkModel::LabelRole).toString());
1842        }
1843
1844        connect(menu, SIGNAL(openTriggered(QString)), SLOT(on_bookmark_openTriggered(QString)));
1845        connect(menu, SIGNAL(openInNewTabTriggered(QString)), SLOT(on_bookmark_openInNewTabTriggered(QString)));
1846        connect(menu, SIGNAL(jumpToPageTriggered(QString,int)), SLOT(on_bookmark_jumpToPageTriggered(QString,int)));
1847        connect(menu, SIGNAL(removeBookmarkTriggered(QString)), SLOT(on_bookmark_removeBookmarkTriggered(QString)));
1848
1849        m_bookmarksMenu->addMenu(menu);
1850    }
1851}
1852
1853void MainWindow::on_bookmark_openTriggered(const QString& absoluteFilePath)
1854{
1855    if(m_tabWidget->currentIndex() != -1)
1856    {
1857        open(absoluteFilePath);
1858    }
1859    else
1860    {
1861        openInNewTab(absoluteFilePath);
1862    }
1863}
1864
1865void MainWindow::on_bookmark_openInNewTabTriggered(const QString& absoluteFilePath)
1866{
1867    openInNewTab(absoluteFilePath);
1868}
1869
1870void MainWindow::on_bookmark_jumpToPageTriggered(const QString& absoluteFilePath, int page)
1871{
1872    jumpToPageOrOpenInNewTab(absoluteFilePath, page);
1873}
1874
1875void MainWindow::on_bookmark_removeBookmarkTriggered(const QString& absoluteFilePath)
1876{
1877    BookmarkModel* model = BookmarkModel::fromPath(absoluteFilePath);
1878
1879    if(model == m_bookmarksView->model())
1880    {
1881        m_bookmarksView->setModel(0);
1882    }
1883
1884    BookmarkModel::forgetPath(absoluteFilePath);
1885
1886    m_bookmarksMenuIsDirty = true;
1887    scheduleSaveBookmarks();
1888}
1889
1890void MainWindow::on_contents_triggered()
1891{
1892    if(m_helpDialog.isNull())
1893    {
1894        m_helpDialog = new HelpDialog();
1895
1896        m_helpDialog->show();
1897        m_helpDialog->setAttribute(Qt::WA_DeleteOnClose);
1898
1899        connect(this, SIGNAL(destroyed()), m_helpDialog, SLOT(close()));
1900    }
1901
1902    m_helpDialog->raise();
1903    m_helpDialog->activateWindow();
1904}
1905
1906void MainWindow::on_about_triggered()
1907{
1908    QString about1,about2,about3,about4,about5,about6;
1909    about1 = trUtf8("Terepaima es una lector de documento PDF que usa QT. ");
1910    about2 = trUtf8("Pueden visualizar el código del ");
1911    about3 = trUtf8("Para mayor información ver ");
1912    about4 = trUtf8("Esta aplicación esta basada en qpdfview ");
1913    about5 = trUtf8("Centro Nacional de Desarrollo e Investigación en Tecnologías Libres 2016");
1914    about6 = trUtf8("Permite verificar y mostrar detalles de la firma electrónica del documento");
1915    QMessageBox::about(this, tr("Acerca de terepaima"), (tr("<p><b>Terepaima %1</b></p><p>").arg(APPLICATION_VERSION) + about1 + tr("</p><p>") + about6 + tr("</p><p>") + about4 + tr(" <a href=\"https://launchpad.net/qpdfview\">launchpad.net/qpdfview</a></p>"
1916                                                      "<p>Esta versión incluye:"
1917                                                      "<ul>")
1918#ifdef WITH_PDF
1919                                                      + tr("<li>PDF support using Poppler %1</li>").arg(POPPLER_VERSION)
1920#endif // WITH_PDF
1921#ifdef WITH_PS
1922                                                      + tr("<li>PS support using libspectre %1</li>").arg(LIBSPECTRE_VERSION)
1923#endif // WITH_PS
1924#ifdef WITH_DJVU
1925                                                      + tr("<li>DjVu support using DjVuLibre %1</li>").arg(DJVULIBRE_VERSION)
1926#endif // WITH_DJVU
1927#ifdef WITH_FITZ
1928                                                      + tr("<li>PDF support using Fitz %1</li>").arg(FITZ_VERSION)
1929#endif // WITH_FITZ
1930#ifdef WITH_CUPS
1931                                                      + tr("<li>Printing support using CUPS %1</li>").arg(CUPS_VERSION)
1932#endif // WITH_CUPS
1933                                                      + tr("</ul>"
1934                                                           "<p> Equipo de trabajo: <br> <b> ") + about5 + tr(" </b> <a href=\"http://www.cenditel.gob.ve/\">CENDITEL</a></p>")
1935                                                      + tr("<ul><li>Pedro Buitrago pbuitrago@cenditel.gob.ve</li>")
1936                                                      + tr("<li>Victor Bravo vbravo@cenditel.gob.ve</li>")
1937                                                      + tr("<li>Antonio Araujo araujo@cenditel.gob.ve</li>")
1938                                                      + tr("<li>Argenis Osorio aosorio@cenditel.gob.ve</li>")
1939                                                      + tr("<li>Jose Sulbaran jsulbaran@cenditel.gob.ve</li>")
1940                                                      + tr("<li>Cipriano Alvarado calvarado@cenditel.gob.ve</li></u></p>")
1941                                                      + tr("<p>") + about3 + tr("<a href=\"https://tibisay.cenditel.gob.ve/visorpdf\">terepaima</a></p>")
1942                                                      + tr("<p>") + about2 + tr("<a href=\https://tibisay.cenditel.gob.ve/visorpdf/browser/visorpdf\>Proyecto</a></p>")));
1943}
1944
1945void MainWindow::on_focusCurrentPage_activated()
1946{
1947    m_currentPageSpinBox->setFocus();
1948    m_currentPageSpinBox->selectAll();
1949}
1950
1951void MainWindow::on_focusScaleFactor_activated()
1952{
1953    m_scaleFactorComboBox->setFocus();
1954    m_scaleFactorComboBox->lineEdit()->selectAll();
1955}
1956
1957void MainWindow::on_toggleToolBars_triggered(bool checked)
1958{
1959    if(checked)
1960    {
1961        m_tabWidget->setTabBarPolicy(static_cast< TabWidget::TabBarPolicy >(m_tabBarHadPolicy));
1962
1963        m_fileToolBar->setVisible(m_fileToolBarWasVisible);
1964        m_editToolBar->setVisible(m_editToolBarWasVisible);
1965        m_viewToolBar->setVisible(m_viewToolBarWasVisible);
1966    }
1967    else
1968    {
1969        m_tabBarHadPolicy = static_cast< int >(m_tabWidget->tabBarPolicy());
1970
1971        m_fileToolBarWasVisible = m_fileToolBar->isVisible();
1972        m_editToolBarWasVisible = m_editToolBar->isVisible();
1973        m_viewToolBarWasVisible = m_viewToolBar->isVisible();
1974
1975        m_tabWidget->setTabBarPolicy(TabWidget::TabBarAlwaysOff);
1976
1977        m_fileToolBar->setVisible(false);
1978        m_editToolBar->setVisible(false);
1979        m_viewToolBar->setVisible(false);
1980    }
1981}
1982
1983void MainWindow::on_toggleMenuBar_triggered(bool checked)
1984{
1985    menuBar()->setVisible(checked);
1986}
1987
1988void MainWindow::on_searchInitiated(const QString& text, bool modified)
1989{
1990    if(text.isEmpty())
1991    {
1992        return;
1993    }
1994
1995    const bool allTabs = s_settings->mainWindow().extendedSearchDock() ? !modified : modified;
1996    const bool matchCase = m_matchCaseCheckBox->isChecked();
1997    const bool wholeWords = m_wholeWordsCheckBox->isChecked();
1998
1999    if(allTabs)
2000    {
2001        for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
2002        {
2003            tab(index)->startSearch(text, matchCase, wholeWords);
2004        }
2005    }
2006    else
2007    {
2008        currentTab()->startSearch(text, matchCase, wholeWords);
2009    }
2010}
2011
2012void MainWindow::on_highlightAll_clicked(bool checked)
2013{
2014    currentTab()->setHighlightAll(checked);
2015}
2016
2017void MainWindow::on_dock_dockLocationChanged(Qt::DockWidgetArea area)
2018{
2019    QDockWidget* dock = qobject_cast< QDockWidget* >(sender());
2020
2021    if(dock == 0)
2022    {
2023        return;
2024    }
2025
2026    QDockWidget::DockWidgetFeatures features = dock->features();
2027
2028    if(area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea)
2029    {
2030        features |= QDockWidget::DockWidgetVerticalTitleBar;
2031    }
2032    else
2033    {
2034        features &= ~QDockWidget::DockWidgetVerticalTitleBar;
2035    }
2036
2037    dock->setFeatures(features);
2038}
2039
2040void MainWindow::on_outline_sectionCountChanged()
2041{
2042    if(m_outlineView->header()->count() > 0)
2043    {
2044#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2045
2046        m_outlineView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
2047
2048#else
2049
2050        m_outlineView->header()->setResizeMode(0, QHeaderView::Stretch);
2051
2052#endif // QT_VERSION
2053    }
2054
2055    if(m_outlineView->header()->count() > 1)
2056    {
2057#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2058
2059        m_outlineView->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
2060
2061#else
2062
2063        m_outlineView->header()->setResizeMode(1, QHeaderView::ResizeToContents);
2064
2065#endif // QT_VERSION
2066    }
2067
2068    m_outlineView->header()->setMinimumSectionSize(0);
2069    m_outlineView->header()->setStretchLastSection(false);
2070    m_outlineView->header()->setVisible(false);
2071}
2072
2073void MainWindow::on_outline_clicked(const QModelIndex& index)
2074{
2075    bool ok = false;
2076    const int page = index.data(Model::Document::PageRole).toInt(&ok);
2077    const qreal left = index.data(Model::Document::LeftRole).toReal();
2078    const qreal top = index.data(Model::Document::TopRole).toReal();
2079
2080    if(ok)
2081    {
2082        currentTab()->jumpToPage(page, true, left, top);
2083    }
2084}
2085
2086void MainWindow::on_properties_sectionCountChanged()
2087{
2088    qDebug("on_properties_sectionCountChanged()");
2089    if(m_propertiesView->horizontalHeader()->count() > 0)
2090    {
2091#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2092
2093        m_propertiesView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
2094
2095#else
2096
2097        m_propertiesView->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
2098
2099#endif // QT_VERSION
2100    }
2101
2102    if(m_propertiesView->horizontalHeader()->count() > 1)
2103    {
2104#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2105
2106        m_propertiesView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
2107
2108#else
2109
2110        m_propertiesView->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
2111
2112#endif // QT_VERSION
2113    }
2114
2115    m_propertiesView->horizontalHeader()->setVisible(false);
2116
2117
2118    if(m_propertiesView->verticalHeader()->count() > 0)
2119    {
2120#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2121
2122        m_propertiesView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
2123
2124#else
2125
2126        m_propertiesView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
2127
2128#endif // QT_VERSION
2129    }
2130
2131    m_propertiesView->verticalHeader()->setVisible(false);
2132}
2133
2134
2135void MainWindow::on_detailsSignatureView_sectionCountChanged()
2136{
2137    qDebug("Entro a on_detailsSignatureView_sectionCountChanged()");
2138}
2139
2140
2141void MainWindow::on_thumbnails_dockLocationChanged(Qt::DockWidgetArea area)
2142{
2143    qDebug("on_thumbnails_dockLocationChanged");
2144    for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
2145    {
2146        tab(index)->setThumbnailsOrientation(area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea ? Qt::Horizontal : Qt::Vertical);
2147    }
2148}
2149
2150void MainWindow::on_thumbnails_verticalScrollBar_valueChanged(int value)
2151{
2152    qDebug("on_thumbnails_verticalScrollBar_valueChanged");
2153    Q_UNUSED(value);
2154
2155    if(m_thumbnailsView->scene() != 0)
2156    {
2157        const QRectF visibleRect = m_thumbnailsView->mapToScene(m_thumbnailsView->viewport()->rect()).boundingRect();
2158
2159        foreach(ThumbnailItem* page, currentTab()->thumbnailItems())
2160        {
2161            if(!page->boundingRect().translated(page->pos()).intersects(visibleRect))
2162            {
2163                page->cancelRender();
2164            }
2165        }
2166    }
2167}
2168
2169void MainWindow::on_bookmarks_sectionCountChanged()
2170{
2171    qDebug("on_bookmarks_sectionCountChanged");
2172    if(m_bookmarksView->horizontalHeader()->count() > 0)
2173    {
2174#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2175
2176        m_bookmarksView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
2177
2178#else
2179
2180        m_bookmarksView->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
2181
2182#endif // QT_VERSION
2183    }
2184
2185    if(m_bookmarksView->horizontalHeader()->count() > 1)
2186    {
2187#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2188
2189        m_bookmarksView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
2190
2191#else
2192
2193        m_bookmarksView->horizontalHeader()->setResizeMode(1, QHeaderView::ResizeToContents);
2194
2195#endif // QT_VERSION
2196    }
2197
2198    m_bookmarksView->horizontalHeader()->setMinimumSectionSize(0);
2199    m_bookmarksView->horizontalHeader()->setStretchLastSection(false);
2200    m_bookmarksView->horizontalHeader()->setVisible(false);
2201
2202    if(m_bookmarksView->verticalHeader()->count() > 0)
2203    {
2204#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2205
2206        m_bookmarksView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
2207
2208#else
2209
2210        m_bookmarksView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
2211
2212#endif // QT_VERSION
2213    }
2214
2215    m_bookmarksView->verticalHeader()->setVisible(false);
2216}
2217
2218void MainWindow::on_bookmarks_clicked(const QModelIndex& index)
2219{
2220    bool ok = false;
2221    const int page = index.data(BookmarkModel::PageRole).toInt(&ok);
2222
2223    if(ok)
2224    {
2225        currentTab()->jumpToPage(page);
2226    }
2227}
2228
2229void MainWindow::on_bookmarks_contextMenuRequested(const QPoint& pos)
2230{
2231    qDebug("on_bookmarks_contextMenuRequested");
2232    QMenu menu;
2233
2234    menu.addActions(QList< QAction* >() << m_previousBookmarkAction << m_nextBookmarkAction);
2235    menu.addSeparator();
2236    menu.addAction(m_addBookmarkAction);
2237
2238    QAction* removeBookmarkAction = menu.addAction(tr("&Remove bookmark"));
2239    QAction* editBookmarkAction = menu.addAction(tr("&Edit bookmark"));
2240
2241    const QModelIndex index = m_bookmarksView->indexAt(pos);
2242
2243    removeBookmarkAction->setVisible(index.isValid());
2244    editBookmarkAction->setVisible(index.isValid());
2245
2246    const QAction* action = menu.exec(m_bookmarksView->mapToGlobal(pos));
2247
2248    if(action == removeBookmarkAction)
2249    {
2250        BookmarkModel* model = qobject_cast< BookmarkModel* >(m_bookmarksView->model());
2251
2252        if(model != 0)
2253        {
2254            model->removeBookmark(BookmarkItem(index.data(BookmarkModel::PageRole).toInt()));
2255
2256            if(model->isEmpty())
2257            {
2258                m_bookmarksView->setModel(0);
2259
2260                BookmarkModel::forgetPath(currentTab()->fileInfo().absoluteFilePath());
2261            }
2262
2263            m_bookmarksMenuIsDirty = true;
2264            scheduleSaveBookmarks();
2265        }
2266
2267    }
2268    else if(action == editBookmarkAction)
2269    {
2270        BookmarkModel* model = qobject_cast< BookmarkModel* >(m_bookmarksView->model());
2271
2272        if(model != 0)
2273        {
2274            BookmarkItem bookmark(index.data(BookmarkModel::PageRole).toInt());
2275
2276            model->findBookmark(bookmark);
2277
2278            QScopedPointer< BookmarkDialog > dialog(new BookmarkDialog(bookmark, this));
2279
2280            if(dialog->exec() == QDialog::Accepted)
2281            {
2282                model->addBookmark(bookmark);
2283
2284                m_bookmarksMenuIsDirty = true;
2285                scheduleSaveBookmarks();
2286            }
2287        }
2288    }
2289}
2290
2291void MainWindow::on_search_sectionCountChanged()
2292{
2293    if(m_searchView->header()->count() > 0)
2294    {
2295#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
2296
2297        m_searchView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
2298
2299#else
2300
2301        m_searchView->header()->setResizeMode(0, QHeaderView::Stretch);
2302
2303#endif // QT_VERSION
2304    }
2305
2306    m_searchView->header()->setMinimumSectionSize(0);
2307    m_searchView->header()->setStretchLastSection(false);
2308    m_searchView->header()->setVisible(false);
2309}
2310
2311void MainWindow::on_search_visibilityChanged(bool visible)
2312{
2313    if(!visible)
2314    {
2315        m_searchLineEdit->stopTimer();
2316        m_searchLineEdit->setProgress(0);
2317
2318        for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
2319        {
2320            tab(index)->cancelSearch();
2321            tab(index)->clearResults();
2322        }
2323
2324        if(m_tabWidget->currentWidget() != 0)
2325        {
2326            m_tabWidget->currentWidget()->setFocus();
2327        }
2328    }
2329}
2330
2331void MainWindow::on_search_clicked(const QModelIndex& index)
2332{
2333    DocumentView* tab = SearchModel::instance()->viewForIndex(index);
2334
2335    m_tabWidget->setCurrentWidget(tab);
2336
2337    tab->findResult(index);
2338}
2339
2340void MainWindow::on_saveDatabase_timeout()
2341{
2342    if(s_settings->mainWindow().restoreTabs())
2343    {
2344        s_database->saveTabs(tabs());
2345    }
2346
2347    if(s_settings->mainWindow().restoreBookmarks())
2348    {
2349        s_database->saveBookmarks();
2350    }
2351
2352    if(s_settings->mainWindow().restorePerFileSettings())
2353    {
2354        foreach(DocumentView* tab, tabs())
2355        {
2356            s_database->savePerFileSettings(tab);
2357        }
2358    }
2359}
2360
2361bool MainWindow::eventFilter(QObject* target, QEvent* event)
2362{
2363    // This event filter is used to override any keyboard shortcuts if the outline widget has the focus.
2364    if(target == m_outlineView && event->type() == QEvent::ShortcutOverride)
2365    {
2366        QKeyEvent* keyEvent = static_cast< QKeyEvent* >(event);
2367
2368        const bool modifiers = keyEvent->modifiers().testFlag(Qt::ControlModifier) || keyEvent->modifiers().testFlag(Qt::ShiftModifier);
2369        const bool keys = keyEvent->key() == Qt::Key_Right || keyEvent->key() == Qt::Key_Left || keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down;
2370
2371        if(modifiers && keys)
2372        {
2373            keyEvent->accept();
2374            return true;
2375        }
2376    }
2377    // This event filter is used to fit the thumbnails into the thumbnails view if this is enabled in the settings.
2378    else if(target == m_thumbnailsView && event->type() == QEvent::Resize)
2379    {
2380        if(DocumentView* tab = currentTab())
2381        {
2382            tab->setThumbnailsViewportSize(m_thumbnailsView->viewport()->size());
2383        }
2384    }
2385
2386    return QMainWindow::eventFilter(target, event);
2387}
2388
2389void MainWindow::closeEvent(QCloseEvent* event)
2390{
2391    m_searchDock->setVisible(false);
2392
2393    for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
2394    {
2395        if(!saveModifications(tab(index)))
2396        {
2397            m_tabWidget->setCurrentIndex(index);
2398
2399            event->setAccepted(false);
2400            return;
2401        }
2402    }
2403
2404    if(s_settings->mainWindow().restoreTabs())
2405    {
2406        s_database->saveTabs(tabs());
2407    }
2408    else
2409    {
2410        s_database->clearTabs();
2411    }
2412
2413    if(s_settings->mainWindow().restoreBookmarks())
2414    {
2415        s_database->saveBookmarks();
2416    }
2417    else
2418    {
2419        s_database->clearBookmarks();
2420    }
2421
2422    s_settings->mainWindow().setRecentlyUsed(s_settings->mainWindow().trackRecentlyUsed() ? m_recentlyUsedMenu->filePaths() : QStringList());
2423
2424    s_settings->documentView().setMatchCase(m_matchCaseCheckBox->isChecked());
2425    s_settings->documentView().setWholeWords(m_wholeWordsCheckBox->isChecked());
2426
2427    s_settings->mainWindow().setGeometry(m_fullscreenAction->isChecked() ? m_fullscreenAction->data().toByteArray() : saveGeometry());
2428    s_settings->mainWindow().setState(saveState());
2429
2430    QMainWindow::closeEvent(event);
2431}
2432
2433void MainWindow::dragEnterEvent(QDragEnterEvent* event)
2434{
2435    if(event->mimeData()->hasUrls())
2436    {
2437        event->acceptProposedAction();
2438    }
2439}
2440
2441void MainWindow::dropEvent(QDropEvent* event)
2442{
2443    if(event->mimeData()->hasUrls())
2444    {
2445        event->acceptProposedAction();
2446
2447        disconnectCurrentTabChanged();
2448
2449        foreach(const QUrl& url, event->mimeData()->urls())
2450        {
2451#if QT_VERSION >= QT_VERSION_CHECK(4,8,0)
2452            if(url.isLocalFile())
2453#else
2454            if(url.scheme() == "file")
2455#endif // QT_VERSION
2456            {
2457                openInNewTab(url.toLocalFile());
2458            }
2459        }
2460
2461        reconnectCurrentTabChanged();
2462    }
2463}
2464
2465void MainWindow::prepareStyle()
2466{
2467    if(s_settings->mainWindow().hasIconTheme())
2468    {
2469        QIcon::setThemeName(s_settings->mainWindow().iconTheme());
2470    }
2471
2472    if(s_settings->mainWindow().hasStyleSheet())
2473    {
2474        qApp->setStyleSheet(s_settings->mainWindow().styleSheet());
2475    }
2476
2477    ProxyStyle* style = new ProxyStyle();
2478
2479    style->setScrollableMenus(s_settings->mainWindow().scrollableMenus());
2480
2481    qApp->setStyle(style);
2482}
2483
2484inline DocumentView* MainWindow::currentTab() const
2485{
2486    return qobject_cast< DocumentView* >(m_tabWidget->currentWidget());
2487}
2488
2489inline DocumentView* MainWindow::tab(int index) const
2490{
2491    return qobject_cast< DocumentView* >(m_tabWidget->widget(index));
2492}
2493
2494QList< DocumentView* > MainWindow::tabs() const
2495{
2496    QList< DocumentView* > tabs;
2497
2498    for(int index = 0, count = m_tabWidget->count(); index < count; ++index)
2499    {
2500        tabs.append(tab(index));
2501    }
2502
2503    return tabs;
2504}
2505
2506bool MainWindow::senderIsCurrentTab() const
2507{
2508     return sender() == m_tabWidget->currentWidget() || qobject_cast< DocumentView* >(sender()) == 0;
2509}
2510
2511int MainWindow::addTab(DocumentView* tab)
2512{
2513    const int index = s_settings->mainWindow().newTabNextToCurrentTab() ?
2514                m_tabWidget->insertTab(m_tabWidget->currentIndex() + 1, tab, tab->title()) :
2515                m_tabWidget->addTab(tab, tab->title());
2516
2517    m_tabWidget->setTabToolTip(index, tab->fileInfo().absoluteFilePath());
2518    m_tabWidget->setCurrentIndex(index);
2519
2520    return index;
2521}
2522
2523void MainWindow::closeTab(DocumentView* tab)
2524{
2525    if(s_settings->mainWindow().keepRecentlyClosed())
2526    {
2527        foreach(QAction* tabAction, m_tabsMenu->actions())
2528        {
2529            if(tabAction->parent() == tab)
2530            {
2531                m_tabsMenu->removeAction(tabAction);
2532                m_tabWidget->removeTab(m_tabWidget->indexOf(tab));
2533
2534                tab->setParent(this);
2535                tab->setVisible(false);
2536
2537                m_recentlyClosedMenu->addTabAction(tabAction);
2538
2539                break;
2540            }
2541        }
2542    }
2543    else
2544    {
2545        delete tab;
2546    }
2547
2548    if(s_settings->mainWindow().exitAfterLastTab() && m_tabWidget->count() == 0)
2549    {
2550        close();
2551    }
2552}
2553
2554bool MainWindow::saveModifications(DocumentView* tab)
2555{
2556    s_database->savePerFileSettings(tab);
2557    scheduleSaveTabs();
2558
2559    if(tab->wasModified())
2560    {
2561        const int button = QMessageBox::warning(this, tr("Warning"), tr("The document '%1' has been modified. Do you want to save your changes?").arg(tab->fileInfo().filePath()), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Save);
2562
2563        if(button == QMessageBox::Save)
2564        {
2565            const QString filePath = QFileDialog::getSaveFileName(this, tr("Save as"), tab->fileInfo().filePath(), tab->saveFilter().join(";;"));
2566
2567            if(!filePath.isEmpty())
2568            {
2569                if(tab->save(filePath, true))
2570                {
2571                    return true;
2572                }
2573                else
2574                {
2575                    QMessageBox::warning(this, tr("Warning"), tr("Could not save as '%1'.").arg(filePath));
2576                }
2577            }
2578        }
2579        else if(button == QMessageBox::Discard)
2580        {
2581            return true;
2582        }
2583
2584        return false;
2585    }
2586
2587    return true;
2588}
2589
2590void MainWindow::disconnectCurrentTabChanged()
2591{
2592    disconnect(m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(on_tabWidget_currentChanged(int)));
2593}
2594
2595void MainWindow::reconnectCurrentTabChanged()
2596{
2597    connect(m_tabWidget, SIGNAL(currentChanged(int)), this, SLOT(on_tabWidget_currentChanged(int)));
2598
2599    on_tabWidget_currentChanged(m_tabWidget->currentIndex());
2600}
2601
2602void MainWindow::setWindowTitleForCurrentTab()
2603{
2604    QString currentPage;
2605    QString tabText;
2606    QString instanceName;
2607
2608    if(m_tabWidget->currentIndex() != -1)
2609    {
2610        if(s_settings->mainWindow().currentPageInWindowTitle())
2611        {
2612            currentPage = QString(" (%1 / %2)").arg(currentTab()->currentPage()).arg(currentTab()->numberOfPages());
2613        }
2614
2615        tabText = m_tabWidget->tabText(m_tabWidget->currentIndex()) + currentPage + QLatin1String("[*] - ");
2616    }
2617
2618    if(s_settings->mainWindow().instanceNameInWindowTitle() && !qApp->objectName().isEmpty())
2619    {
2620        instanceName = QLatin1String(" (") + qApp->objectName() + QLatin1String(")");
2621    }
2622
2623//    setWindowTitle(tabText + QLatin1String("qpdfview") + instanceName);
2624    setWindowTitle(tabText + QLatin1String("Terepaima") + instanceName);
2625}
2626
2627void MainWindow::setCurrentPageSuffixForCurrentTab()
2628{
2629    QString suffix;
2630
2631    if(m_tabWidget->currentIndex() != -1)
2632    {
2633        const int currentPage = currentTab()->currentPage();
2634        const int numberOfPages = currentTab()->numberOfPages();
2635
2636        const QString& defaultPageLabel = currentTab()->defaultPageLabelFromNumber(currentPage);
2637        const QString& pageLabel = currentTab()->pageLabelFromNumber(currentPage);
2638
2639        const QString& lastDefaultPageLabel = currentTab()->defaultPageLabelFromNumber(numberOfPages);
2640
2641        if((s_settings->mainWindow().usePageLabel() || currentTab()->hasFrontMatter()) && defaultPageLabel != pageLabel)
2642        {
2643            suffix = QString(" (%1 / %2)").arg(defaultPageLabel).arg(lastDefaultPageLabel);
2644        }
2645        else
2646        {
2647            suffix = QString(" / %1").arg(lastDefaultPageLabel);
2648        }
2649    }
2650    else
2651    {
2652        suffix = QLatin1String(" / 1");
2653    }
2654
2655    m_currentPageSpinBox->setSuffix(suffix);
2656}
2657
2658BookmarkModel* MainWindow::bookmarkModelForCurrentTab(bool create)
2659{
2660    return BookmarkModel::fromPath(currentTab()->fileInfo().absoluteFilePath(), create);
2661}
2662
2663QAction* MainWindow::sourceLinkActionForCurrentTab(QObject* parent, const QPoint& pos)
2664{
2665    QAction* action = createTemporaryAction(parent, QString(), QLatin1String("openSourceLink"));
2666
2667    if(const DocumentView::SourceLink sourceLink = currentTab()->sourceLink(pos))
2668    {
2669        action->setText(tr("Edit '%1' at %2,%3...").arg(sourceLink.name).arg(sourceLink.line).arg(sourceLink.column));
2670        action->setData(QVariant::fromValue(sourceLink));
2671    }
2672    else
2673    {
2674        action->setVisible(false);
2675    }
2676
2677    return action;
2678}
2679
2680void MainWindow::prepareDatabase()
2681{
2682    if(s_database == 0)
2683    {
2684        s_database = Database::instance();
2685    }
2686
2687    m_saveDatabaseTimer = new QTimer(this);
2688    m_saveDatabaseTimer->setSingleShot(true);
2689    m_saveDatabaseTimer->setInterval(s_settings->mainWindow().saveDatabaseInterval());
2690
2691    connect(m_saveDatabaseTimer, SIGNAL(timeout()), SLOT(on_saveDatabase_timeout()));
2692}
2693
2694void MainWindow::scheduleSaveDatabase()
2695{
2696    if(!m_saveDatabaseTimer->isActive() && m_saveDatabaseTimer->interval() > 0)
2697    {
2698        m_saveDatabaseTimer->start();
2699    }
2700}
2701
2702void MainWindow::scheduleSaveTabs()
2703{
2704    if(s_settings->mainWindow().restoreTabs())
2705    {
2706        scheduleSaveDatabase();
2707    }
2708}
2709
2710void MainWindow::scheduleSaveBookmarks()
2711{
2712    if(s_settings->mainWindow().restoreBookmarks())
2713    {
2714        scheduleSaveDatabase();
2715    }
2716}
2717
2718void MainWindow::scheduleSavePerFileSettings()
2719{
2720    if(s_settings->mainWindow().restorePerFileSettings())
2721    {
2722        scheduleSaveDatabase();
2723    }
2724}
2725
2726void MainWindow::createWidgets()
2727{
2728    m_tabWidget = new TabWidget(this);
2729
2730    m_tabWidget->setDocumentMode(true);
2731    m_tabWidget->setMovable(true);
2732    m_tabWidget->setTabsClosable(true);
2733    m_tabWidget->setElideMode(Qt::ElideRight);
2734
2735    m_tabWidget->setTabPosition(static_cast< QTabWidget::TabPosition >(s_settings->mainWindow().tabPosition()));
2736    m_tabWidget->setTabBarPolicy(static_cast< TabWidget::TabBarPolicy >(s_settings->mainWindow().tabVisibility()));
2737    m_tabWidget->setSpreadTabs(s_settings->mainWindow().spreadTabs());
2738
2739    setCentralWidget(m_tabWidget);
2740
2741    connect(m_tabWidget, SIGNAL(currentChanged(int)), SLOT(on_tabWidget_currentChanged(int)));
2742    connect(m_tabWidget, SIGNAL(tabCloseRequested(int)), SLOT(on_tabWidget_tabCloseRequested(int)));
2743    connect(m_tabWidget, SIGNAL(tabContextMenuRequested(QPoint,int)), SLOT(on_tabWidget_tabContextMenuRequested(QPoint,int)));
2744
2745    // current page
2746
2747    m_currentPageSpinBox = new MappingSpinBox(new TextValueMapper(this), this);
2748
2749    m_currentPageSpinBox->setAlignment(Qt::AlignCenter);
2750    m_currentPageSpinBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
2751    m_currentPageSpinBox->setKeyboardTracking(false);
2752
2753    connect(m_currentPageSpinBox, SIGNAL(editingFinished()), SLOT(on_currentPage_editingFinished()));
2754    connect(m_currentPageSpinBox, SIGNAL(returnPressed()), SLOT(on_currentPage_returnPressed()));
2755
2756    m_currentPageAction = new QWidgetAction(this);
2757
2758    m_currentPageAction->setObjectName(QLatin1String("currentPage"));
2759    m_currentPageAction->setDefaultWidget(m_currentPageSpinBox);
2760
2761    // scale factor
2762
2763    m_scaleFactorComboBox = new ComboBox(this);
2764
2765    m_scaleFactorComboBox->setEditable(true);
2766    m_scaleFactorComboBox->setInsertPolicy(QComboBox::NoInsert);
2767
2768    m_scaleFactorComboBox->addItem(tr("Page width"));
2769    m_scaleFactorComboBox->addItem(tr("Page size"));
2770    m_scaleFactorComboBox->addItem("50 %", 0.5);
2771    m_scaleFactorComboBox->addItem("75 %", 0.75);
2772    m_scaleFactorComboBox->addItem("100 %", 1.0);
2773    m_scaleFactorComboBox->addItem("125 %", 1.25);
2774    m_scaleFactorComboBox->addItem("150 %", 1.5);
2775    m_scaleFactorComboBox->addItem("200 %", 2.0);
2776    m_scaleFactorComboBox->addItem("300 %", 3.0);
2777    m_scaleFactorComboBox->addItem("400 %", 4.0);
2778    m_scaleFactorComboBox->addItem("500 %", 5.0);
2779
2780    connect(m_scaleFactorComboBox, SIGNAL(activated(int)), SLOT(on_scaleFactor_activated(int)));
2781    connect(m_scaleFactorComboBox->lineEdit(), SIGNAL(editingFinished()), SLOT(on_scaleFactor_editingFinished()));
2782    connect(m_scaleFactorComboBox->lineEdit(), SIGNAL(returnPressed()), SLOT(on_scaleFactor_returnPressed()));
2783
2784    m_scaleFactorAction = new QWidgetAction(this);
2785
2786    m_scaleFactorAction->setObjectName(QLatin1String("scaleFactor"));
2787    m_scaleFactorAction->setDefaultWidget(m_scaleFactorComboBox);
2788
2789    // search
2790
2791    m_searchLineEdit = new SearchLineEdit(this);
2792    m_matchCaseCheckBox = new QCheckBox(tr("Match &case"), this);
2793    m_wholeWordsCheckBox = new QCheckBox(tr("Whole &words"), this);
2794    m_highlightAllCheckBox = new QCheckBox(tr("Highlight &all"), this);
2795
2796    connect(m_searchLineEdit, SIGNAL(searchInitiated(QString,bool)), SLOT(on_searchInitiated(QString,bool)));
2797    connect(m_matchCaseCheckBox, SIGNAL(clicked()), m_searchLineEdit, SLOT(startTimer()));
2798    connect(m_wholeWordsCheckBox, SIGNAL(clicked()), m_searchLineEdit, SLOT(startTimer()));
2799    connect(m_highlightAllCheckBox, SIGNAL(clicked(bool)), SLOT(on_highlightAll_clicked(bool)));
2800
2801    m_matchCaseCheckBox->setChecked(s_settings->documentView().matchCase());
2802    m_wholeWordsCheckBox->setChecked(s_settings->documentView().wholeWords());
2803}
2804
2805QAction* MainWindow::createAction(const QString& text, const QString& objectName, const QIcon& icon, const QList< QKeySequence >& shortcuts, const char* member, bool checkable, bool checked)
2806{
2807    QAction* action = new QAction(text, this);
2808
2809    action->setObjectName(objectName);
2810    action->setIcon(icon);
2811    action->setShortcuts(shortcuts);
2812
2813    if(!objectName.isEmpty())
2814    {
2815        s_shortcutHandler->registerAction(action);
2816    }
2817
2818    if(checkable)
2819    {
2820        action->setCheckable(true);
2821        action->setChecked(checked);
2822
2823        connect(action, SIGNAL(triggered(bool)), member);
2824    }
2825    else
2826    {
2827        action->setIconVisibleInMenu(true);
2828
2829        connect(action, SIGNAL(triggered()), member);
2830    }
2831
2832    addAction(action);
2833
2834    return action;
2835}
2836
2837inline QAction* MainWindow::createAction(const QString& text, const QString& objectName, const QIcon& icon, const QKeySequence& shortcut, const char* member, bool checkable, bool checked)
2838{
2839    return createAction(text, objectName, icon, QList< QKeySequence >() << shortcut, member, checkable, checked);
2840}
2841
2842inline QAction* MainWindow::createAction(const QString& text, const QString& objectName, const QString& iconName, const QList< QKeySequence >& shortcuts, const char* member, bool checkable, bool checked)
2843{
2844    return createAction(text, objectName, loadIconWithFallback(iconName), shortcuts, member, checkable, checked);
2845}
2846
2847inline QAction* MainWindow::createAction(const QString& text, const QString& objectName, const QString& iconName, const QKeySequence& shortcut, const char* member, bool checkable, bool checked)
2848{
2849    return createAction(text, objectName, iconName, QList< QKeySequence >() << shortcut, member, checkable, checked);
2850}
2851
2852void MainWindow::createActions()
2853{
2854    // file
2855
2856    m_openAction = createAction(tr("&Open..."), QLatin1String("open"), QLatin1String("document-open"), QKeySequence::Open, SLOT(on_open_triggered()));
2857    m_openInNewTabAction = createAction(tr("Open in new &tab..."), QLatin1String("openInNewTab"), QLatin1String("tab-new"), QKeySequence::AddTab, SLOT(on_openInNewTab_triggered()));
2858    m_openCopyInNewTabAction = createAction(tr("Open &copy in new tab"), QLatin1String("openCopyInNewTab"), QLatin1String("tab-new"), QKeySequence(), SLOT(on_openCopyInNewTab_triggered()));
2859    m_openContainingFolderAction = createAction(tr("Open containing &folder"), QLatin1String("openContainingFolder"), QLatin1String("folder"), QKeySequence(), SLOT(on_openContainingFolder_triggered()));
2860    m_refreshAction = createAction(tr("&Refresh"), QLatin1String("refresh"), QLatin1String("view-refresh"), QKeySequence::Refresh, SLOT(on_refresh_triggered()));
2861    m_saveCopyAction = createAction(tr("&Save copy..."), QLatin1String("saveCopy"), QLatin1String("document-save"), QKeySequence::Save, SLOT(on_saveCopy_triggered()));
2862    m_saveAsAction = createAction(tr("Save &as..."), QLatin1String("saveAs"), QLatin1String("document-save-as"), QKeySequence::SaveAs, SLOT(on_saveAs_triggered()));
2863    m_printAction = createAction(tr("&Print..."), QLatin1String("print"), QLatin1String("document-print"), QKeySequence::Print, SLOT(on_print_triggered()));
2864    m_exitAction = createAction(tr("E&xit"), QLatin1String("exit"), QIcon::fromTheme("application-exit"), QKeySequence::Quit, SLOT(close()));
2865    m_verify_signature = createAction(trUtf8("&Verificar firma electrónica..."), QLatin1String("Verify signature"), QLatin1String("verify-signature"), QKeySequence(), SLOT(on_verify_signature()));
2866
2867    // edit
2868
2869    m_previousPageAction = createAction(tr("&Previous page"), QLatin1String("previousPage"), QLatin1String("go-previous"), QKeySequence(Qt::Key_Backspace), SLOT(on_previousPage_triggered()));
2870    m_nextPageAction = createAction(tr("&Next page"), QLatin1String("nextPage"), QLatin1String("go-next"), QKeySequence(Qt::Key_Space), SLOT(on_nextPage_triggered()));
2871    m_firstPageAction = createAction(tr("&First page"), QLatin1String("firstPage"), QLatin1String("go-first"), QList< QKeySequence >() << QKeySequence(Qt::Key_Home) << QKeySequence(Qt::KeypadModifier + Qt::Key_Home), SLOT(on_firstPage_triggered()));
2872    m_lastPageAction = createAction(tr("&Last page"), QLatin1String("lastPage"), QLatin1String("go-last"), QList< QKeySequence >() << QKeySequence(Qt::Key_End) << QKeySequence(Qt::KeypadModifier + Qt::Key_End), SLOT(on_lastPage_triggered()));
2873
2874    m_setFirstPageAction = createAction(tr("&Set first page..."), QLatin1String("setFirstPage"), QIcon(), QKeySequence(), SLOT(on_setFirstPage_triggered()));
2875
2876    m_jumpToPageAction = createAction(tr("&Jump to page..."), QLatin1String("jumpToPage"), QLatin1String("go-jump"), QKeySequence(Qt::CTRL + Qt::Key_J), SLOT(on_jumpToPage_triggered()));
2877
2878    m_jumpBackwardAction = createAction(tr("Jump &backward"), QLatin1String("jumpBackward"), QLatin1String("media-seek-backward"), QKeySequence(Qt::CTRL + Qt::Key_Return), SLOT(on_jumpBackward_triggered()));
2879    m_jumpForwardAction = createAction(tr("Jump for&ward"), QLatin1String("jumpForward"), QLatin1String("media-seek-forward"), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Return), SLOT(on_jumpForward_triggered()));
2880
2881    m_searchAction = createAction(tr("&Search..."), QLatin1String("search"), QLatin1String("edit-find"), QKeySequence::Find, SLOT(on_search_triggered()));
2882    m_findPreviousAction = createAction(tr("Find previous"), QLatin1String("findPrevious"), QLatin1String("go-up"), QKeySequence::FindPrevious, SLOT(on_findPrevious_triggered()));
2883    m_findNextAction = createAction(tr("Find next"), QLatin1String("findNext"), QLatin1String("go-down"), QKeySequence::FindNext, SLOT(on_findNext_triggered()));
2884    m_cancelSearchAction = createAction(tr("Cancel search"), QLatin1String("cancelSearch"), QLatin1String("process-stop"), QKeySequence(Qt::Key_Escape), SLOT(on_cancelSearch_triggered()));
2885
2886    m_copyToClipboardModeAction = createAction(tr("&Copy to clipboard"), QLatin1String("copyToClipboardMode"), QLatin1String("edit-copy"), QKeySequence(Qt::CTRL + Qt::Key_C), SLOT(on_copyToClipboardMode_triggered(bool)), true);
2887    m_addAnnotationModeAction = createAction(tr("&Add annotation"), QLatin1String("addAnnotationMode"), QLatin1String("mail-attachment"), QKeySequence(Qt::CTRL + Qt::Key_A), SLOT(on_addAnnotationMode_triggered(bool)), true);
2888
2889    m_settingsAction = createAction(tr("Settings..."), QString(), QIcon(), QKeySequence(), SLOT(on_settings_triggered()));
2890
2891    // view
2892
2893    m_continuousModeAction = createAction(tr("&Continuous"), QLatin1String("continuousMode"), QIcon(QLatin1String(":icons/continuous.svg")), QKeySequence(Qt::CTRL + Qt::Key_7), SLOT(on_continuousMode_triggered(bool)), true);
2894    m_twoPagesModeAction = createAction(tr("&Two pages"), QLatin1String("twoPagesMode"), QIcon(QLatin1String(":icons/two-pages.svg")), QKeySequence(Qt::CTRL + Qt::Key_6), SLOT(on_twoPagesMode_triggered(bool)), true);
2895    m_twoPagesWithCoverPageModeAction = createAction(tr("Two pages &with cover page"), QLatin1String("twoPagesWithCoverPageMode"), QIcon(QLatin1String(":icons/two-pages-with-cover-page.svg")), QKeySequence(Qt::CTRL + Qt::Key_5), SLOT(on_twoPagesWithCoverPageMode_triggered(bool)), true);
2896    m_multiplePagesModeAction = createAction(tr("&Multiple pages"), QLatin1String("multiplePagesMode"), QIcon(QLatin1String(":icons/multiple-pages.svg")), QKeySequence(Qt::CTRL + Qt::Key_4), SLOT(on_multiplePagesMode_triggered(bool)), true);
2897
2898    m_rightToLeftModeAction = createAction(tr("Right to left"), QLatin1String("rightToLeftMode"), QIcon(QLatin1String(":icons/right-to-left.svg")), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_R), SLOT(on_rightToLeftMode_triggered(bool)), true);
2899
2900    m_zoomInAction = createAction(tr("Zoom &in"), QLatin1String("zoomIn"), QLatin1String("zoom-in"), QKeySequence(Qt::CTRL + Qt::Key_Up), SLOT(on_zoomIn_triggered()));
2901    m_zoomOutAction = createAction(tr("Zoom &out"), QLatin1String("zoomOut"), QLatin1String("zoom-out"), QKeySequence(Qt::CTRL + Qt::Key_Down), SLOT(on_zoomOut_triggered()));
2902    m_originalSizeAction = createAction(tr("Original &size"), QLatin1String("originalSize"), QLatin1String("zoom-original"), QKeySequence(Qt::CTRL + Qt::Key_0), SLOT(on_originalSize_triggered()));
2903
2904    m_fitToPageWidthModeAction = createAction(tr("Fit to page width"), QLatin1String("fitToPageWidthMode"), QIcon(QLatin1String(":icons/fit-to-page-width.svg")), QKeySequence(Qt::CTRL + Qt::Key_9), SLOT(on_fitToPageWidthMode_triggered(bool)), true);
2905    m_fitToPageSizeModeAction = createAction(tr("Fit to page size"), QLatin1String("fitToPageSizeMode"), QIcon(QLatin1String(":icons/fit-to-page-size.svg")), QKeySequence(Qt::CTRL + Qt::Key_8), SLOT(on_fitToPageSizeMode_triggered(bool)), true);
2906
2907    m_rotateLeftAction = createAction(tr("Rotate &left"), QLatin1String("rotateLeft"), QLatin1String("object-rotate-left"), QKeySequence(Qt::CTRL + Qt::Key_Left), SLOT(on_rotateLeft_triggered()));
2908    m_rotateRightAction = createAction(tr("Rotate &right"), QLatin1String("rotateRight"), QLatin1String("object-rotate-right"), QKeySequence(Qt::CTRL + Qt::Key_Right), SLOT(on_rotateRight_triggered()));
2909
2910    m_invertColorsAction = createAction(tr("Invert colors"), QLatin1String("invertColors"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_I), SLOT(on_invertColors_triggered(bool)), true);
2911    m_convertToGrayscaleAction = createAction(tr("Convert to grayscale"), QLatin1String("convertToGrayscale"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_U), SLOT(on_convertToGrayscale_triggered(bool)), true);
2912    m_trimMarginsAction = createAction(tr("Trim margins"), QLatin1String("trimMargins"), QIcon(), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_U), SLOT(on_trimMargins_triggered(bool)), true);
2913
2914    m_darkenWithPaperColorAction = createAction(tr("Darken with paper color"), QLatin1String("darkenWithPaperColor"), QIcon(), QKeySequence(), SLOT(on_darkenWithPaperColor_triggered(bool)), true);
2915    m_lightenWithPaperColorAction = createAction(tr("Lighten with paper color"), QLatin1String("lightenWithPaperColor"), QIcon(), QKeySequence(), SLOT(on_lightenWithPaperColor_triggered(bool)), true);
2916
2917    m_fontsAction = createAction(tr("Fonts..."), QString(), QIcon(), QKeySequence(), SLOT(on_fonts_triggered()));
2918
2919    m_fullscreenAction = createAction(tr("&Fullscreen"), QLatin1String("fullscreen"), QLatin1String("view-fullscreen"), QKeySequence(Qt::Key_F11), SLOT(on_fullscreen_triggered(bool)), true);
2920    m_presentationAction = createAction(tr("&Presentation..."), QLatin1String("presentation"), QLatin1String("x-office-presentation"), QKeySequence(Qt::Key_F12), SLOT(on_presentation_triggered()));
2921
2922    // tabs
2923
2924    m_previousTabAction = createAction(tr("&Previous tab"), QLatin1String("previousTab"), QIcon(), QKeySequence::PreviousChild, SLOT(on_previousTab_triggered()));
2925    m_nextTabAction = createAction(tr("&Next tab"), QLatin1String("nextTab"), QIcon(), QKeySequence::NextChild, SLOT(on_nextTab_triggered()));
2926
2927    m_closeTabAction = createAction(tr("&Close tab"), QLatin1String("closeTab"), QIcon::fromTheme("window-close"), QKeySequence(Qt::CTRL + Qt::Key_W), SLOT(on_closeTab_triggered()));
2928    m_closeAllTabsAction = createAction(tr("Close &all tabs"), QLatin1String("closeAllTabs"), QIcon(), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_W), SLOT(on_closeAllTabs_triggered()));
2929    m_closeAllTabsButCurrentTabAction = createAction(tr("Close all tabs &but current tab"), QLatin1String("closeAllTabsButCurrent"), QIcon(), QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_W), SLOT(on_closeAllTabsButCurrentTab_triggered()));
2930
2931    m_restoreMostRecentlyClosedTabAction = createAction(tr("Restore &most recently closed tab"), QLatin1String("restoreMostRecentlyClosedTab"), QIcon(), QKeySequence(Qt::ALT + Qt::SHIFT + Qt::Key_W), SLOT(on_restoreMostRecentlyClosedTab_triggered()));
2932
2933    // tab shortcuts
2934
2935    for(int index = 0; index < 9; ++index)
2936    {
2937        m_tabShortcuts[index] = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_1 + index), this, SLOT(on_tabShortcut_activated()));
2938    }
2939
2940    // bookmarks
2941
2942    m_previousBookmarkAction = createAction(tr("&Previous bookmark"), QLatin1String("previousBookmarkAction"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_PageUp), SLOT(on_previousBookmark_triggered()));
2943    m_nextBookmarkAction = createAction(tr("&Next bookmark"), QLatin1String("nextBookmarkAction"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_PageDown), SLOT(on_nextBookmark_triggered()));
2944
2945    m_addBookmarkAction = createAction(tr("&Add bookmark"), QLatin1String("addBookmark"), QIcon(), QKeySequence(Qt::CTRL + Qt::Key_B), SLOT(on_addBookmark_triggered()));
2946    m_removeBookmarkAction = createAction(tr("&Remove bookmark"), QLatin1String("removeBookmark"), QIcon(), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_B), SLOT(on_removeBookmark_triggered()));
2947    m_removeAllBookmarksAction = createAction(tr("Remove all bookmarks"), QLatin1String("removeAllBookmark"), QIcon(), QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_B), SLOT(on_removeAllBookmarks_triggered()));
2948
2949    // help
2950
2951    m_contentsAction = createAction(tr("&Contents"), QLatin1String("contents"), QIcon::fromTheme("help-contents"), QKeySequence::HelpContents, SLOT(on_contents_triggered()));
2952    m_aboutAction = createAction(tr("&About"), QString(), QIcon::fromTheme("help-about"), QKeySequence(), SLOT(on_about_triggered()));
2953
2954    // tool bars and menu bar
2955
2956    m_toggleToolBarsAction = createAction(tr("Toggle tool bars"), QLatin1String("toggleToolBars"), QIcon(), QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_T), SLOT(on_toggleToolBars_triggered(bool)), true, true);
2957    m_toggleMenuBarAction = createAction(tr("Toggle menu bar"), QLatin1String("toggleMenuBar"), QIcon(), QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_M), SLOT(on_toggleMenuBar_triggered(bool)), true, true);
2958
2959    // progress and error icons
2960
2961    s_settings->pageItem().setProgressIcon(loadIconWithFallback(QLatin1String("image-loading")));
2962    s_settings->pageItem().setErrorIcon(loadIconWithFallback(QLatin1String("image-missing")));
2963}
2964
2965QToolBar* MainWindow::createToolBar(const QString& text, const QString& objectName, const QStringList& actionNames, const QList< QAction* >& actions)
2966{
2967    QToolBar* toolBar = addToolBar(text);
2968    toolBar->setObjectName(objectName);
2969
2970    addWidgetActions(toolBar, actionNames, actions);
2971
2972    toolBar->toggleViewAction()->setObjectName(objectName + QLatin1String("ToggleView"));
2973    s_shortcutHandler->registerAction(toolBar->toggleViewAction());
2974
2975    return toolBar;
2976}
2977
2978void MainWindow::createToolBars()
2979{
2980    m_fileToolBar = createToolBar(tr("&File"), QLatin1String("fileToolBar"), s_settings->mainWindow().fileToolBar(),
2981                                  QList< QAction* >() << m_openAction << m_openInNewTabAction << m_openContainingFolderAction << m_refreshAction << m_saveCopyAction << m_saveAsAction << m_printAction << m_verify_signature);
2982
2983    m_editToolBar = createToolBar(tr("&Edit"), QLatin1String("editToolBar"), s_settings->mainWindow().editToolBar(),
2984                                  QList< QAction* >() << m_currentPageAction << m_previousPageAction << m_nextPageAction << m_firstPageAction << m_lastPageAction << m_jumpToPageAction << m_searchAction << m_jumpBackwardAction << m_jumpForwardAction << m_copyToClipboardModeAction << m_addAnnotationModeAction);
2985
2986    m_viewToolBar = createToolBar(tr("&View"), QLatin1String("viewToolBar"), s_settings->mainWindow().viewToolBar(),
2987                                  QList< QAction* >() << m_scaleFactorAction << m_continuousModeAction << m_twoPagesModeAction << m_twoPagesWithCoverPageModeAction << m_multiplePagesModeAction << m_rightToLeftModeAction << m_zoomInAction << m_zoomOutAction << m_originalSizeAction << m_fitToPageWidthModeAction << m_fitToPageSizeModeAction << m_rotateLeftAction << m_rotateRightAction << m_fullscreenAction << m_presentationAction);
2988
2989    m_focusCurrentPageShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_K), this, SLOT(on_focusCurrentPage_activated()));
2990    m_focusScaleFactorShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_L), this, SLOT(on_focusScaleFactor_activated()));
2991}
2992
2993QDockWidget* MainWindow::createDock(const QString& text, const QString& objectName, const QKeySequence& toggleViewShortcut)
2994{
2995    QDockWidget* dock = new QDockWidget(text, this);
2996    dock->setObjectName(objectName);
2997    dock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
2998
2999#ifdef Q_OS_WIN
3000
3001    dock->setWindowTitle(dock->windowTitle().remove(QLatin1Char('&')));
3002
3003#endif // Q_OS_WIN
3004
3005    addDockWidget(Qt::LeftDockWidgetArea, dock);
3006
3007    connect(dock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), SLOT(on_dock_dockLocationChanged(Qt::DockWidgetArea)));
3008
3009    dock->toggleViewAction()->setObjectName(objectName + QLatin1String("ToggleView"));
3010    dock->toggleViewAction()->setShortcut(toggleViewShortcut);
3011
3012    s_shortcutHandler->registerAction(dock->toggleViewAction());
3013
3014    dock->hide();
3015
3016    return dock;
3017}
3018
3019void MainWindow::createSearchDock()
3020{
3021    m_searchDock = new QDockWidget(tr("&Search"), this);
3022    m_searchDock->setObjectName(QLatin1String("searchDock"));
3023    m_searchDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetVerticalTitleBar);
3024
3025#ifdef Q_OS_WIN
3026
3027    m_searchDock->setWindowTitle(m_searchDock->windowTitle().remove(QLatin1Char('&')));
3028
3029#endif // Q_OS_WIN
3030
3031    addDockWidget(Qt::BottomDockWidgetArea, m_searchDock);
3032
3033    connect(m_searchDock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), SLOT(on_dock_dockLocationChanged(Qt::DockWidgetArea)));
3034    connect(m_searchDock, SIGNAL(visibilityChanged(bool)), SLOT(on_search_visibilityChanged(bool)));
3035
3036    m_searchWidget = new QWidget(this);
3037
3038    QToolButton* findPreviousButton = new QToolButton(m_searchWidget);
3039    findPreviousButton->setAutoRaise(true);
3040    findPreviousButton->setDefaultAction(m_findPreviousAction);
3041
3042    QToolButton* findNextButton = new QToolButton(m_searchWidget);
3043    findNextButton->setAutoRaise(true);
3044    findNextButton->setDefaultAction(m_findNextAction);
3045
3046    QToolButton* cancelSearchButton = new QToolButton(m_searchWidget);
3047    cancelSearchButton->setAutoRaise(true);
3048    cancelSearchButton->setDefaultAction(m_cancelSearchAction);
3049
3050    QGridLayout* searchLayout = new QGridLayout(m_searchWidget);
3051    searchLayout->setRowStretch(2, 1);
3052    searchLayout->setColumnStretch(2, 1);
3053    searchLayout->addWidget(m_searchLineEdit, 0, 0, 1, 7);
3054    searchLayout->addWidget(m_matchCaseCheckBox, 1, 0);
3055    searchLayout->addWidget(m_wholeWordsCheckBox, 1, 1);
3056    searchLayout->addWidget(m_highlightAllCheckBox, 1, 2);
3057    searchLayout->addWidget(findPreviousButton, 1, 4);
3058    searchLayout->addWidget(findNextButton, 1, 5);
3059    searchLayout->addWidget(cancelSearchButton, 1, 6);
3060
3061    m_searchDock->setWidget(m_searchWidget);
3062
3063    connect(m_searchDock, SIGNAL(visibilityChanged(bool)), m_findPreviousAction, SLOT(setEnabled(bool)));
3064    connect(m_searchDock, SIGNAL(visibilityChanged(bool)), m_findNextAction, SLOT(setEnabled(bool)));
3065    connect(m_searchDock, SIGNAL(visibilityChanged(bool)), m_cancelSearchAction, SLOT(setEnabled(bool)));
3066
3067    m_searchDock->setVisible(false);
3068
3069    m_findPreviousAction->setEnabled(false);
3070    m_findNextAction->setEnabled(false);
3071    m_cancelSearchAction->setEnabled(false);
3072
3073    if(s_settings->mainWindow().extendedSearchDock())
3074    {
3075        m_searchDock->setFeatures(m_searchDock->features() | QDockWidget::DockWidgetClosable);
3076
3077        m_searchDock->toggleViewAction()->setObjectName(QLatin1String("searchDockToggleView"));
3078        m_searchDock->toggleViewAction()->setShortcut(QKeySequence(Qt::Key_F10));
3079
3080        s_shortcutHandler->registerAction(m_searchDock->toggleViewAction());
3081
3082        m_searchView = new QTreeView(m_searchWidget);
3083        m_searchView->setAlternatingRowColors(true);
3084        m_searchView->setUniformRowHeights(true);
3085        m_searchView->setEditTriggers(QAbstractItemView::NoEditTriggers);
3086        m_searchView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
3087        m_searchView->setSelectionMode(QAbstractItemView::SingleSelection);
3088        m_searchView->setSelectionBehavior(QAbstractItemView::SelectRows);
3089
3090        connect(m_searchView->header(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_search_sectionCountChanged()));
3091        connect(m_searchView, SIGNAL(clicked(QModelIndex)), SLOT(on_search_clicked(QModelIndex)));
3092        connect(m_searchView, SIGNAL(activated(QModelIndex)), SLOT(on_search_clicked(QModelIndex)));
3093
3094        m_searchView->setItemDelegate(new SearchItemDelegate(m_searchView));
3095        m_searchView->setModel(SearchModel::instance());
3096
3097        searchLayout->addWidget(m_searchView, 2, 0, 1, 6);
3098    }
3099    else
3100    {
3101        m_searchView = 0;
3102    }
3103}
3104
3105void MainWindow::createDocks()
3106{
3107    // outline
3108    qDebug("createDocks()");
3109    m_outlineDock = createDock(tr("&Outline"), QLatin1String("outlineDock"), QKeySequence(Qt::Key_F6));
3110
3111    m_outlineView = new TreeView(Model::Document::ExpansionRole, this);
3112    m_outlineView->setAlternatingRowColors(true);
3113    m_outlineView->setEditTriggers(QAbstractItemView::NoEditTriggers);
3114    m_outlineView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
3115    m_outlineView->setSelectionMode(QAbstractItemView::SingleSelection);
3116    m_outlineView->setSelectionBehavior(QAbstractItemView::SelectRows);
3117
3118    m_outlineView->installEventFilter(this);
3119
3120    connect(m_outlineView->header(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_outline_sectionCountChanged()));
3121    connect(m_outlineView, SIGNAL(clicked(QModelIndex)), SLOT(on_outline_clicked(QModelIndex)));
3122    connect(m_outlineView, SIGNAL(activated(QModelIndex)), SLOT(on_outline_clicked(QModelIndex)));
3123
3124    m_outlineDock->setWidget(m_outlineView);
3125
3126    // properties
3127
3128    m_propertiesDock = createDock(tr("&Properties"), QLatin1String("propertiesDock"), QKeySequence(Qt::Key_F7));
3129
3130    m_propertiesView = new QTableView(this);
3131    m_propertiesView->setAlternatingRowColors(true);
3132    m_propertiesView->setTabKeyNavigation(false);
3133    m_propertiesView->setEditTriggers(QAbstractItemView::NoEditTriggers);
3134    m_propertiesView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
3135
3136    connect(m_propertiesView->horizontalHeader(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_properties_sectionCountChanged()));
3137
3138    m_propertiesDock->setWidget(m_propertiesView);
3139
3140    //______________________________________________________________
3141    // verify signature
3142    m_detailsSignatureDock = createDock(trUtf8("&Verificar firma electrónica"), QLatin1String("verifySignature-Dock"), QKeySequence(Qt::Key_F12));
3143    //m_detailsSignatureDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
3144    //QStringList itens;
3145    //m_detailsSignatureView = new QListWidget(m_detailsSignatureDock);
3146    m_detailsSignatureView = new QTableView(this);
3147    m_detailsSignatureView->setAlternatingRowColors(true);
3148    m_detailsSignatureView->setTabKeyNavigation(false);
3149    m_detailsSignatureView->setEditTriggers(QAbstractItemView::NoEditTriggers);
3150    m_detailsSignatureView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
3151    m_detailsSignatureView->verticalHeader()->hide();
3152
3153        //prueba->addItems(QStringList() << verify_signature().toStdString());
3154//    QStringList itens;
3155//    itens << "Cargar archivo PDF para verificar la firma ";
3156////    for(int i = 0; i<1; i++) {
3157
3158////            itens << "Cargar archivo PDF para verificar la firma " + QString::number(i);
3159////        }
3160//    m_detailsSignatureView->addItems(itens);
3161
3162//    m_detailsSignatureDock->setWidget(m_detailsSignatureView);
3163
3164
3165   connect(m_detailsSignatureView->horizontalHeader(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_detailsSignatureView_sectionCountChanged()));
3166   //connect(m_detailsSignatureView, SIGNAL(valueChanged(int)), SLOT(on_detailsSignatureView_sectionCountChanged()));
3167
3168    m_detailsSignatureDock->setWidget(m_detailsSignatureView);
3169    //______________________________________________________________
3170
3171    // thumbnails
3172
3173    m_thumbnailsDock = createDock(tr("Thumb&nails"), QLatin1String("thumbnailsDock"), QKeySequence(Qt::Key_F8));
3174
3175    connect(m_thumbnailsDock, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), SLOT(on_thumbnails_dockLocationChanged(Qt::DockWidgetArea)));
3176
3177    m_thumbnailsView = new QGraphicsView(this);
3178
3179    m_thumbnailsView->installEventFilter(this);
3180
3181    connect(m_thumbnailsView->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(on_thumbnails_verticalScrollBar_valueChanged(int)));
3182
3183    m_thumbnailsDock->setWidget(m_thumbnailsView);
3184
3185    // bookmarks
3186
3187    m_bookmarksDock = createDock(tr("Book&marks"), QLatin1String("bookmarksDock"), QKeySequence(Qt::Key_F9));
3188
3189    m_bookmarksView = new QTableView(this);
3190    m_bookmarksView->setShowGrid(false);
3191    m_bookmarksView->setAlternatingRowColors(true);
3192    m_bookmarksView->setEditTriggers(QAbstractItemView::NoEditTriggers);
3193    m_bookmarksView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
3194    m_bookmarksView->setSelectionMode(QAbstractItemView::SingleSelection);
3195    m_bookmarksView->setSelectionBehavior(QAbstractItemView::SelectRows);
3196    m_bookmarksView->setContextMenuPolicy(Qt::CustomContextMenu);
3197
3198    connect(m_bookmarksView->horizontalHeader(), SIGNAL(sectionCountChanged(int,int)), SLOT(on_bookmarks_sectionCountChanged()));
3199    connect(m_bookmarksView, SIGNAL(clicked(QModelIndex)), SLOT(on_bookmarks_clicked(QModelIndex)));
3200    connect(m_bookmarksView, SIGNAL(activated(QModelIndex)), SLOT(on_bookmarks_clicked(QModelIndex)));
3201    connect(m_bookmarksView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(on_bookmarks_contextMenuRequested(QPoint)));
3202
3203    m_bookmarksDock->setWidget(m_bookmarksView);
3204
3205    // search
3206
3207    createSearchDock();
3208}
3209
3210void MainWindow::createMenus()
3211{
3212    // file
3213
3214    m_fileMenu = menuBar()->addMenu(tr("&File"));
3215    m_fileMenu->addActions(QList< QAction* >() << m_openAction << m_openInNewTabAction);
3216
3217    m_recentlyUsedMenu = new RecentlyUsedMenu(s_settings->mainWindow().recentlyUsed(), s_settings->mainWindow().recentlyUsedCount(), this);
3218
3219    connect(m_recentlyUsedMenu, SIGNAL(openTriggered(QString)), SLOT(on_recentlyUsed_openTriggered(QString)));
3220
3221    if(s_settings->mainWindow().trackRecentlyUsed())
3222    {
3223        m_fileMenu->addMenu(m_recentlyUsedMenu);
3224
3225        setToolButtonMenu(m_fileToolBar, m_openAction, m_recentlyUsedMenu);
3226        setToolButtonMenu(m_fileToolBar, m_openInNewTabAction, m_recentlyUsedMenu);
3227    }
3228
3229    m_fileMenu->addActions(QList< QAction* >() << m_refreshAction << m_saveCopyAction << m_saveAsAction << m_printAction << m_verify_signature);
3230    m_fileMenu->addSeparator();
3231    m_fileMenu->addAction(m_exitAction);
3232
3233    // edit
3234
3235    m_editMenu = menuBar()->addMenu(tr("&Edit"));
3236    m_editMenu->addActions(QList< QAction* >() << m_previousPageAction << m_nextPageAction << m_firstPageAction << m_lastPageAction << m_jumpToPageAction);
3237    m_editMenu->addSeparator();
3238    m_editMenu->addActions(QList< QAction* >() << m_jumpBackwardAction << m_jumpForwardAction);
3239    m_editMenu->addSeparator();
3240    m_editMenu->addActions(QList< QAction* >() << m_searchAction << m_findPreviousAction << m_findNextAction << m_cancelSearchAction);
3241    m_editMenu->addSeparator();
3242    m_editMenu->addActions(QList< QAction* >() << m_copyToClipboardModeAction << m_addAnnotationModeAction);
3243    m_editMenu->addSeparator();
3244    m_editMenu->addAction(m_settingsAction);
3245
3246    // view
3247
3248    m_viewMenu = menuBar()->addMenu(tr("&View"));
3249    m_viewMenu->addActions(QList< QAction* >() << m_continuousModeAction << m_twoPagesModeAction << m_twoPagesWithCoverPageModeAction << m_multiplePagesModeAction);
3250    m_viewMenu->addSeparator();
3251    m_viewMenu->addAction(m_rightToLeftModeAction);
3252    m_viewMenu->addSeparator();
3253    m_viewMenu->addActions(QList< QAction* >() << m_zoomInAction << m_zoomOutAction << m_originalSizeAction << m_fitToPageWidthModeAction << m_fitToPageSizeModeAction);
3254    m_viewMenu->addSeparator();
3255    m_viewMenu->addActions(QList< QAction* >() << m_rotateLeftAction << m_rotateRightAction);
3256    m_viewMenu->addSeparator();
3257    m_viewMenu->addActions(QList< QAction* >() << m_invertColorsAction << m_convertToGrayscaleAction << m_trimMarginsAction);
3258
3259    m_compositionModeMenu = m_viewMenu->addMenu(tr("Composition"));
3260    m_compositionModeMenu->addAction(m_darkenWithPaperColorAction);
3261    m_compositionModeMenu->addAction(m_lightenWithPaperColorAction);
3262
3263    m_viewMenu->addSeparator();
3264
3265    QMenu* toolBarsMenu = m_viewMenu->addMenu(tr("&Tool bars"));
3266    toolBarsMenu->addActions(QList< QAction* >() << m_fileToolBar->toggleViewAction() << m_editToolBar->toggleViewAction() << m_viewToolBar->toggleViewAction());
3267
3268    QMenu* docksMenu = m_viewMenu->addMenu(tr("&Docks"));
3269    docksMenu->addActions(QList< QAction* >() << m_outlineDock->toggleViewAction() << m_propertiesDock->toggleViewAction() << m_thumbnailsDock->toggleViewAction() << m_bookmarksDock->toggleViewAction() << m_detailsSignatureDock->toggleViewAction());
3270
3271    if(s_settings->mainWindow().extendedSearchDock())
3272    {
3273        docksMenu->addAction(m_searchDock->toggleViewAction());
3274    }
3275
3276    m_viewMenu->addAction(m_fontsAction);
3277    m_viewMenu->addSeparator();
3278    m_viewMenu->addActions(QList< QAction* >() << m_fullscreenAction << m_presentationAction);
3279
3280    // tabs
3281
3282    m_tabsMenu = new SearchableMenu(tr("&Tabs"), this);
3283    menuBar()->addMenu(m_tabsMenu);
3284
3285    m_tabsMenu->setSearchable(s_settings->mainWindow().searchableMenus());
3286
3287    m_tabsMenu->addActions(QList< QAction* >() << m_previousTabAction << m_nextTabAction);
3288    m_tabsMenu->addSeparator();
3289    m_tabsMenu->addActions(QList< QAction* >() << m_closeTabAction << m_closeAllTabsAction << m_closeAllTabsButCurrentTabAction);
3290
3291    m_recentlyClosedMenu = new RecentlyClosedMenu(s_settings->mainWindow().recentlyClosedCount(), this);
3292
3293    connect(m_recentlyClosedMenu, SIGNAL(tabActionTriggered(QAction*)), SLOT(on_recentlyClosed_tabActionTriggered(QAction*)));
3294
3295    if(s_settings->mainWindow().keepRecentlyClosed())
3296    {
3297        m_tabsMenu->addMenu(m_recentlyClosedMenu);
3298        m_tabsMenu->addAction(m_restoreMostRecentlyClosedTabAction);
3299    }
3300
3301    m_tabsMenu->addSeparator();
3302
3303    // bookmarks
3304
3305    m_bookmarksMenu = new SearchableMenu(tr("&Bookmarks"), this);
3306    menuBar()->addMenu(m_bookmarksMenu);
3307
3308    m_bookmarksMenu->setSearchable(s_settings->mainWindow().searchableMenus());
3309
3310    connect(m_bookmarksMenu, SIGNAL(aboutToShow()), this, SLOT(on_bookmarksMenu_aboutToShow()));
3311
3312    m_bookmarksMenuIsDirty = true;
3313
3314    // help
3315
3316    m_helpMenu = menuBar()->addMenu(tr("&Help"));
3317    m_helpMenu->addActions(QList< QAction* >() << m_contentsAction << m_aboutAction);
3318}
3319
3320#ifdef WITH_DBUS
3321
3322MainWindowAdaptor::MainWindowAdaptor(MainWindow* mainWindow) : QDBusAbstractAdaptor(mainWindow)
3323{
3324}
3325
3326void MainWindowAdaptor::raiseAndActivate()
3327{
3328    mainWindow()->raise();
3329    mainWindow()->activateWindow();
3330}
3331
3332bool MainWindowAdaptor::open(const QString& absoluteFilePath, int page, const QRectF& highlight, bool quiet)
3333{
3334    return mainWindow()->open(absoluteFilePath, page, highlight, quiet);
3335}
3336
3337bool MainWindowAdaptor::openInNewTab(const QString& absoluteFilePath, int page, const QRectF& highlight, bool quiet)
3338{
3339    return mainWindow()->openInNewTab(absoluteFilePath, page, highlight, quiet);
3340}
3341
3342bool MainWindowAdaptor::jumpToPageOrOpenInNewTab(const QString& absoluteFilePath, int page, bool refreshBeforeJump, const QRectF& highlight, bool quiet)
3343{
3344    return mainWindow()->jumpToPageOrOpenInNewTab(absoluteFilePath, page, refreshBeforeJump, highlight, quiet);
3345}
3346
3347void MainWindowAdaptor::startSearch(const QString& text)
3348{
3349    mainWindow()->startSearch(text);
3350}
3351
3352#define ONLY_IF_CURRENT_TAB if(mainWindow()->m_tabWidget->currentIndex() == -1) { return; }
3353
3354void MainWindowAdaptor::previousPage()
3355{
3356    ONLY_IF_CURRENT_TAB
3357
3358    mainWindow()->on_previousPage_triggered();
3359}
3360
3361void MainWindowAdaptor::nextPage()
3362{
3363    ONLY_IF_CURRENT_TAB
3364
3365    mainWindow()->on_nextPage_triggered();
3366}
3367
3368void MainWindowAdaptor::firstPage()
3369{
3370    ONLY_IF_CURRENT_TAB
3371
3372    mainWindow()->on_firstPage_triggered();
3373}
3374
3375void MainWindowAdaptor::lastPage()
3376{
3377    ONLY_IF_CURRENT_TAB
3378
3379    mainWindow()->on_lastPage_triggered();
3380}
3381
3382void MainWindowAdaptor::previousBookmark()
3383{
3384    ONLY_IF_CURRENT_TAB
3385
3386    mainWindow()->on_previousBookmark_triggered();
3387}
3388
3389void MainWindowAdaptor::nextBookmark()
3390{
3391    ONLY_IF_CURRENT_TAB
3392
3393    mainWindow()->on_nextBookmark_triggered();
3394}
3395
3396bool MainWindowAdaptor::jumpToBookmark(const QString& label)
3397{
3398    if(mainWindow()->m_tabWidget->currentIndex() == -1) { return false; }
3399
3400    const BookmarkModel* model = mainWindow()->bookmarkModelForCurrentTab();
3401
3402    if(model != 0)
3403    {
3404        for(int row = 0, rowCount = model->rowCount(); row < rowCount; ++row)
3405        {
3406            const QModelIndex index = model->index(row);
3407
3408            if(label == index.data(BookmarkModel::LabelRole).toString())
3409            {
3410                mainWindow()->currentTab()->jumpToPage(index.data(BookmarkModel::PageRole).toInt());
3411
3412                return true;
3413            }
3414        }
3415    }
3416
3417    return false;
3418}
3419
3420void MainWindowAdaptor::continuousModeAction(bool checked)
3421{
3422    ONLY_IF_CURRENT_TAB
3423
3424    mainWindow()->on_continuousMode_triggered(checked);
3425}
3426
3427void MainWindowAdaptor::twoPagesModeAction(bool checked)
3428{
3429    ONLY_IF_CURRENT_TAB
3430
3431    mainWindow()->on_twoPagesMode_triggered(checked);
3432}
3433
3434void MainWindowAdaptor::twoPagesWithCoverPageModeAction(bool checked)
3435{
3436    ONLY_IF_CURRENT_TAB
3437
3438    mainWindow()->on_twoPagesWithCoverPageMode_triggered(checked);
3439}
3440
3441void MainWindowAdaptor::multiplePagesModeAction(bool checked)
3442{
3443    ONLY_IF_CURRENT_TAB
3444
3445    mainWindow()->on_multiplePagesMode_triggered(checked);
3446}
3447
3448void MainWindowAdaptor::fitToPageWidthModeAction(bool checked)
3449{
3450    ONLY_IF_CURRENT_TAB
3451
3452    mainWindow()->on_fitToPageWidthMode_triggered(checked);
3453}
3454
3455void MainWindowAdaptor::fitToPageSizeModeAction(bool checked)
3456{
3457    ONLY_IF_CURRENT_TAB
3458
3459    mainWindow()->on_fitToPageSizeMode_triggered(checked);
3460}
3461
3462void MainWindowAdaptor::convertToGrayscaleAction(bool checked)
3463{
3464    ONLY_IF_CURRENT_TAB
3465
3466    mainWindow()->on_convertToGrayscale_triggered(checked);
3467}
3468
3469void MainWindowAdaptor::invertColorsAction(bool checked)
3470{
3471    ONLY_IF_CURRENT_TAB
3472
3473    mainWindow()->on_invertColors_triggered(checked);
3474}
3475
3476void MainWindowAdaptor::fullscreenAction(bool checked)
3477{
3478    if(mainWindow()->m_fullscreenAction->isChecked() != checked)
3479    {
3480        mainWindow()->m_fullscreenAction->trigger();
3481    }
3482}
3483
3484void MainWindowAdaptor::presentationAction()
3485{
3486    ONLY_IF_CURRENT_TAB
3487
3488    mainWindow()->on_presentation_triggered();
3489}
3490
3491void MainWindowAdaptor::closeTab()
3492{
3493    ONLY_IF_CURRENT_TAB
3494
3495    mainWindow()->on_closeTab_triggered();
3496}
3497
3498void MainWindowAdaptor::closeAllTabs()
3499{
3500    mainWindow()->on_closeAllTabs_triggered();
3501}
3502
3503void MainWindowAdaptor::closeAllTabsButCurrentTab()
3504{
3505    mainWindow()->on_closeAllTabsButCurrentTab_triggered();
3506}
3507
3508// agregando funciones para la verificación de la firma electrónica
3509
3510const char * getReadableSigState(SignatureValidationStatus sig_vs)
3511{
3512  switch(sig_vs) {
3513    case SIGNATURE_VALID:
3514      //return "Signature is Valid.";
3515      return "Firma válida.";
3516
3517    case SIGNATURE_INVALID:
3518      //return "Signature is Invalid.";
3519      return "Firma inválida.";
3520
3521    case SIGNATURE_DIGEST_MISMATCH:
3522      //return "Digest Mismatch.";
3523      return "Digest Mismatch.";
3524
3525    case SIGNATURE_DECODING_ERROR:
3526      //return "Document isn't signed or corrupted data.";
3527      return "El documento no está firmado o datos dañados.";
3528
3529    case SIGNATURE_NOT_VERIFIED:
3530      //return "Signature has not yet been verified.";
3531      return "Firma todavía no se ha verificado.";
3532
3533    default:
3534      //return "Unknown Validation Failure.";
3535      return "Desconocido fallo de validación.";
3536  }
3537}
3538
3539const char * getReadableCertState(CertificateValidationStatus cert_vs)
3540{
3541  switch(cert_vs) {
3542    case CERTIFICATE_TRUSTED:
3543      //return "Certificate is Trusted.";
3544      return "Certificado es de confianza";
3545
3546    case CERTIFICATE_UNTRUSTED_ISSUER:
3547      //return "Certificate issuer isn't Trusted.";
3548      return "Emisor del certificado no es de confianza";
3549
3550    case CERTIFICATE_UNKNOWN_ISSUER:
3551      //return "Certificate issuer is unknown.";
3552      return "Emisor de certificado es desconocido";
3553
3554    case CERTIFICATE_REVOKED:
3555      //return "Certificate has been Revoked.";
3556      return "Certificado ha sido revocado.";
3557
3558    case CERTIFICATE_EXPIRED:
3559      //return "Certificate has Expired";
3560      return "Certificado ha caducado";
3561
3562    case CERTIFICATE_NOT_VERIFIED:
3563      //return "Certificate has not yet been verified.";
3564      return "Certificado aún no ha sido verificado.";
3565
3566    default:
3567      //return "Unknown issue with Certificate or corrupted data.";
3568      return "Problema desconocido con el certificado o datos dañados.";
3569  }
3570}
3571
3572char *getReadableTime(time_t unix_time)
3573{
3574  char * time_str = (char *) gmalloc(64);
3575  strftime(time_str, 64, "%b %d %Y %H:%M:%S", localtime(&unix_time));
3576  return time_str;
3577}
3578
3579static GBool printVersion = gFalse;
3580static GBool printHelp = gFalse;
3581static GBool dontVerifyCert = gFalse;
3582
3583//static const ArgDesc argDesc[] = {
3584//  {"-nocert", argFlag,     &dontVerifyCert,     0,
3585//   "don't perform certificate validation"},
3586
3587//  {"-v",      argFlag,     &printVersion,  0,
3588//   "print copyright and version info"},
3589//  {"-h",      argFlag,     &printHelp,     0,
3590//   "print usage information"},
3591//  {"-help",   argFlag,     &printHelp,     0,
3592//   "print usage information"},
3593//  {"-?",      argFlag,     &printHelp,     0,
3594//   "print usage information"},
3595//  {NULL}
3596//};
3597
3598//fin de agregar funciones para la verificación de firma electrónica
3599
3600//QString MainWindow::verify_signature() {
3601//QStringList MainWindow::verify_signature() {
3602
3603QStandardItemModel *MainWindow::view_table_verify_signature() {
3604
3605    qDebug("view_table_verify_signature");
3606    //m_tableVerifySign = new QTableView();
3607
3608    char *time_str = NULL;
3609    PDFDoc *doc = NULL;
3610    unsigned int sigCount;
3611    GooString * fileName = NULL;
3612    SignatureInfo *sig_info = NULL;
3613    std::vector<FormWidgetSignature*> sig_widgets;
3614    globalParams = new GlobalParams();
3615
3616    int exitCode = 99;
3617    // GBool ok;
3618
3619    QString newfile = currentTab()->fileInfo().absoluteFilePath();
3620
3621    qDebug("***fileName signatures: |%s|",newfile.toUtf8().data());
3622    fileName = new GooString(newfile.toUtf8().data());  // le paso el path del documento PDF para abrirlo
3623
3624    // open PDF file
3625    doc = PDFDocFactory().createPDFDoc(*fileName, NULL, NULL); //abre el documento
3626    if (!doc->isOk()) {
3627        exitCode = 1;
3628        qDebug(".......error");
3629     }
3630
3631     sig_widgets = doc->getSignatureWidgets();
3632     sigCount = sig_widgets.size();
3633
3634     if( sigCount >= 1 ) { //El documento tiene firma electronica
3635         int numColumns = 2;
3636         int numRows = sigCount*5;
3637         QStringList horzHeaders;
3638         horzHeaders << "Atributo" << "Valor";
3639         QStandardItemModel* model = new QStandardItemModel(numRows, numColumns);
3640         model->setHorizontalHeaderLabels(horzHeaders);
3641         QString rowtype, rowvalue;
3642         int countRow = 0;
3643
3644         for (unsigned int i = 0; i < sigCount; i++) {
3645              sig_info = sig_widgets.at(i)->validateSignature(!dontVerifyCert, false);
3646
3647              //**Sección para llenar la tabla
3648              //qDebug() << countRow;
3649              rowtype = trUtf8("Firma número %1").arg(i+1);
3650              QStandardItem* item = new QStandardItem(rowtype);
3651              model->setItem(countRow, 0, item);
3652              countRow ++;
3653              rowtype = trUtf8("   - Nombre común ");
3654              item = new QStandardItem(rowtype);
3655              model->setItem(countRow, 0, item);
3656              rowvalue = sig_info->getSignerName();
3657              item = new QStandardItem(rowvalue);
3658              model->setItem(countRow, 1, item);
3659              countRow ++;
3660              rowtype = trUtf8("   - Hora de la firma ");
3661              item = item = new QStandardItem(rowtype);
3662              model->setItem(countRow, 0, item);
3663              rowvalue = getReadableTime(sig_info->getSigningTime());
3664              item = new QStandardItem(rowvalue);
3665              model->setItem(countRow, 1, item);
3666              countRow ++;
3667              rowtype = trUtf8("   - Validación de la firma ");
3668              item = item = new QStandardItem(rowtype);
3669              model->setItem(countRow, 0, item);
3670              rowvalue = trUtf8(getReadableSigState(sig_info->getSignatureValStatus()));
3671              item = new QStandardItem(rowvalue);
3672              model->setItem(countRow, 1, item);
3673              countRow ++;
3674              rowtype = trUtf8("   - Validación del certificado ");
3675              item = item = new QStandardItem(rowtype);
3676              model->setItem(countRow, 0, item);
3677              rowvalue = getReadableCertState(sig_info->getCertificateValStatus());
3678              item = new QStandardItem(rowvalue);
3679              model->setItem(countRow, 1, item);
3680              countRow ++;
3681              model->takeVerticalHeaderItem(countRow);
3682          }
3683         return model;
3684      }
3685
3686     else { //El documento no tiene firma
3687         QStandardItemModel* model = new QStandardItemModel(1,1);
3688         QString rowtype = trUtf8("El documento no posee firma electrónica");
3689         QStandardItem* item = new QStandardItem(rowtype);
3690         model->setItem(0, 0, item);
3691         return model;
3692     }
3693}
3694
3695QStandardItemModel *MainWindow::verify_signature() {
3696    qDebug("verify_signature");
3697    m_tableVerifySign = new QTableView();
3698
3699
3700    char *time_str = NULL;
3701    PDFDoc *doc = NULL;
3702    unsigned int sigCount;
3703    GooString * fileName = NULL;
3704    SignatureInfo *sig_info = NULL;
3705    std::vector<FormWidgetSignature*> sig_widgets;
3706    globalParams = new GlobalParams();
3707
3708    int exitCode = 99;
3709    // GBool ok;
3710
3711    QString newfile = currentTab()->fileInfo().absoluteFilePath();
3712
3713    qDebug("***fileName signatures: |%s|",newfile.toUtf8().data());
3714    fileName = new GooString(newfile.toUtf8().data());  // le paso el path del documento PDF para abrirlo
3715
3716    // open PDF file
3717    doc = PDFDocFactory().createPDFDoc(*fileName, NULL, NULL); //abre el documento
3718    //qDebug(".......1");
3719    if (!doc->isOk()) {
3720        exitCode = 1;
3721        qDebug(".......error");
3722        //return "Error";
3723        //goto end;
3724     }
3725
3726     //qDebug(".......3");
3727     sig_widgets = doc->getSignatureWidgets();
3728     sigCount = sig_widgets.size();
3729     int numColumns = 2;
3730     int numRows = sigCount*5;
3731     QStringList horzHeaders;
3732     horzHeaders << "Atributo" << "Valor";
3733
3734     QStandardItemModel* model = new QStandardItemModel(numRows, numColumns);
3735     model->setHorizontalHeaderLabels(horzHeaders);
3736     qDebug()<<horzHeaders[0];
3737     qDebug()<<horzHeaders[1];
3738    // model->setHorizontalHeaderLabels(horzheaders);
3739      QStringList itens;
3740      //QStandardItem* item;
3741      QString rowtype, rowvalue;
3742      int countRow = 0;
3743      QString newmessage = trUtf8("Número de firmas: %1 ").arg(sigCount);
3744      newmessage += "\n \n";
3745      for (unsigned int i = 0; i < sigCount; i++) {
3746          sig_info = sig_widgets.at(i)->validateSignature(!dontVerifyCert, false);
3747          //qDebug("Firma %d ", i+1);
3748          newmessage += trUtf8("Firma número %1").arg(i+1);
3749          newmessage += "\n";
3750          //qDebug(sig_info->getSignerName());
3751          newmessage += trUtf8("  - Nombre común: %1  \n").arg(sig_info->getSignerName());
3752          newmessage += trUtf8("  - Hora de la firma: %1f \n").arg(time_str = getReadableTime(sig_info->getSigningTime()));
3753          newmessage += trUtf8("  - Validación de la firma: %1  \n").arg(getReadableSigState(sig_info->getSignatureValStatus()));
3754          newmessage += trUtf8("  - Validación del certificado: %1").arg(getReadableCertState(sig_info->getCertificateValStatus()));
3755          newmessage += \n";
3756          itens << trUtf8("Firma número %1").arg(i+1) + trUtf8("  - Nombre común: %1  \n").arg(sig_info->getSignerName()) + trUtf8("  - Hora de la firma: %1f \n").arg(time_str = getReadableTime(sig_info->getSigningTime())) + trUtf8("  - Validación de la firma: %1  \n").arg(getReadableSigState(sig_info->getSignatureValStatus())) + trUtf8("  - Validación del certificado: %1").arg(getReadableCertState(sig_info->getCertificateValStatus()));
3757
3758          //**Sección para llenar la tabla
3759
3760          rowtype = "Firma " + QString::number(i + 1);
3761          QStandardItem* item = new QStandardItem(rowtype);
3762          model->setItem(countRow, 0, item);
3763          countRow ++;
3764          rowtype = trUtf8("  - Nombre común ");
3765          item = new QStandardItem(rowtype);
3766          model->setItem(countRow, 0, item);
3767          rowvalue = sig_info->getSignerName();
3768          item = new QStandardItem(rowvalue);
3769          model->setItem(countRow, 1, item);
3770          countRow ++;
3771          rowtype = trUtf8("  - Hora de la firma ");
3772          item = item = new QStandardItem(rowtype);
3773          model->setItem(countRow, 0, item);
3774          rowvalue = getReadableTime(sig_info->getSigningTime());
3775          item = new QStandardItem(rowvalue);
3776          model->setItem(countRow, 1, item);
3777          countRow ++;
3778          rowtype = trUtf8("  - Validación de la firma ");
3779          item = item = new QStandardItem(rowtype);
3780          model->setItem(countRow, 0, item);
3781          rowvalue = trUtf8(getReadableSigState(sig_info->getSignatureValStatus()));
3782          item = new QStandardItem(rowvalue);
3783          model->setItem(countRow, 1, item);
3784          countRow ++;
3785          rowtype = trUtf8("  - Validación del certificado ");
3786          item = item = new QStandardItem(rowtype);
3787          model->setItem(countRow, 0, item);
3788          rowvalue = getReadableCertState(sig_info->getCertificateValStatus());
3789          item = new QStandardItem(rowvalue);
3790          model->setItem(countRow, 1, item);
3791          countRow ++;
3792      }
3793      //return newmessage;
3794      qDebug()<<itens;
3795      qDebug("Saliendo**************************************************************************************************************");
3796      //m_tableVerifySign->setModel(model);
3797      //return itens;
3798      return model;
3799 }
3800
3801void MainWindow::on_verify_signature() {
3802
3803    qDebug("Entro a on_verify_signature()");
3804    verify_signature();
3805    char *time_str = NULL;
3806    PDFDoc *doc = NULL;
3807    unsigned int sigCount;
3808    GooString * fileName = NULL;
3809    SignatureInfo *sig_info = NULL;
3810    std::vector<FormWidgetSignature*> sig_widgets;
3811    globalParams = new GlobalParams();
3812
3813    int exitCode = 99;
3814    // GBool ok;
3815
3816    QString newfile = currentTab()->fileInfo().absoluteFilePath();
3817
3818    qDebug("***fileName signatures: |%s|",newfile.toUtf8().data());
3819    fileName = new GooString(newfile.toUtf8().data());  // le paso el path del documento PDF para abrirlo
3820
3821    // open PDF file
3822    doc = PDFDocFactory().createPDFDoc(*fileName, NULL, NULL); //abre el documento
3823    //qDebug(".......1");
3824    if (!doc->isOk()) {
3825        exitCode = 1;
3826        qDebug(".......error");
3827        return;
3828        //goto end;
3829     }
3830
3831     qDebug(".......3");
3832     sig_widgets = doc->getSignatureWidgets();
3833     sigCount = sig_widgets.size();
3834
3835
3836      QString newmessage = trUtf8("Número de firmas: %1 ").arg(sigCount);
3837      newmessage += "\n \n";
3838      //qDebug("fileName number of signatures: %d", sigCount);
3839      //qDebug("****************************");
3840      //qDebug(fileName->getCString());
3841
3842      //***********************
3843//      if (sigCount >= 1) {
3844//          //newmessage =+ trUtf8("Digital Signature Info of: %s\n").arg(fileName->getCString());
3845//          //qDebug(fileName->getCString()); //path del archivo que se abrio
3846//          qDebug("El archivo contiene firma electrónica");
3847//          //printf("Digital Signature Info of: %s\n", fileName->getCString());
3848//        } else {
3849//          //newmessage =+ trUtf8("File '%s' does not contain any signatures\n").arg(fileName->getCString());
3850//          qDebug("El archivo no contiene firma electrónica");
3851//          //printf("File '%s' does not contain any signatures\n", fileName->getCString());
3852//          exitCode = 2;
3853//          return;
3854//          //goto end;
3855//        }
3856
3857        for (unsigned int i = 0; i < sigCount; i++) {
3858          sig_info = sig_widgets.at(i)->validateSignature(!dontVerifyCert, false);
3859          qDebug("Firma %d ", i+1);
3860          //printf("Signature #%u:\n", i+1);
3861          newmessage += trUtf8("Firma número %1").arg(i+1);
3862          newmessage += "\n";
3863          //qDebug("entro al for: %d", i);
3864          //qDebug(i+1);
3865          //printf("  - Signer Certificate Common Name: %s\n", sig_info->getSignerName());
3866          qDebug(sig_info->getSignerName());
3867          newmessage += trUtf8("  - Nombre común: %1  \n").arg(sig_info->getSignerName());
3868          //newmessage += "  \n";
3869          //printf("  - Signing Time: %s\n", time_str = getReadableTime(sig_info->getSigningTime()));
3870          newmessage += trUtf8("  - Hora de la firma: %1f \n").arg(time_str = getReadableTime(sig_info->getSigningTime()));
3871          //newmessage += "  \n";
3872          //newmessage =+ trUtf8("  - Signing Time: %s\n").arg(getReadableTime(sig_info->getSigningTime()));
3873          //printf("  - Signature Validation: %s\n", getReadableSigState(sig_info->getSignatureValStatus()));
3874          newmessage += trUtf8("  - Validación de la firma: %1  \n").arg(trUtf8(getReadableSigState(sig_info->getSignatureValStatus())));
3875
3876          //newmessage =+ trUtf8("  - Signature Validation: %s\n").arg(getReadableSigState(sig_info->getSignatureValStatus()));
3877          //gfree(time_str);
3878          //if (sig_info->getSignatureValStatus() != SIGNATURE_VALID || dontVerifyCert) {
3879            //continue;
3880          //}
3881          //printf("  - Certificate Validation: %s\n", getReadableCertState(sig_info->getCertificateValStatus()));
3882          newmessage += trUtf8("  - Validación del certificado: %1").arg(getReadableCertState(sig_info->getCertificateValStatus()));
3883          newmessage += \n";
3884        }
3885
3886    //***********************
3887
3888
3889    QString my_msg;
3890    my_msg = " Signature #1: \n - Signer Certificate Common Name: Murachi \n - Signing Time: Apr 10 2015 08:26:08  \n - Signature Validation: Signature is Valid. \n - Certificate Validation: Certificate issuer is unknown. \n Signature #2: \n - Signer Certificate Common Name: Juan Hilario \n  - Signing Time: Apr 10 2015 08:27:42 \n - Signature Validation: Signature is Valid. \n  - Certificate Validation: Certificate has Expired \n  Signature #3: \n - Signer Certificate Common Name: Murachi \n - Signing Time: Apr 10 2015 08:48:18 \n - Signature Validation: Signature is Valid. \n - Certificate Validation: Certificate issuer is unknown";
3891
3892    QMessageBox my_msg_Box;
3893    int cont = 1;
3894    if(sigCount == 0) {
3895        my_msg_Box.setWindowTitle("Terepaima");
3896        my_msg_Box.setText("El documento no esta firmado");
3897        my_msg_Box.exec();
3898    }
3899    else {
3900        my_msg_Box.setWindowTitle("Terepaima");
3901        my_msg_Box.setText("El documento esta firmado electronicamente");
3902        my_msg_Box.setDetailedText(newmessage);
3903        my_msg_Box.exec();
3904    }
3905}
3906
3907bool MainWindowAdaptor::closeTab(const QString& absoluteFilePath)
3908{
3909    if(mainWindow()->m_tabWidget->currentIndex() == -1) { return false; }
3910
3911    const QFileInfo fileInfo(absoluteFilePath);
3912
3913    foreach(DocumentView* tab, mainWindow()->tabs())
3914    {
3915        if(tab->fileInfo() == fileInfo)
3916        {
3917            if(mainWindow()->saveModifications(tab))
3918            {
3919                mainWindow()->closeTab(tab);
3920            }
3921
3922            return true;
3923        }
3924    }
3925
3926    return false;
3927}
3928
3929#undef ONLY_IF_CURRENT_TAB
3930
3931inline MainWindow* MainWindowAdaptor::mainWindow() const
3932{
3933    return qobject_cast< MainWindow* >(parent());
3934}
3935
3936# endif // WITH_DBUS
3937
3938} // qpdfview
Note: See TracBrowser for help on using the repository browser.