qpdfview 0.4.18.tar.gz release, cc642e7fa74029373ca9b9fbc29adc4883f8b455130a78ad54746d6844a0396c
Šī revīzija ir iekļauta:
187
sources/annotationwidgets.cpp
Parasts fails
187
sources/annotationwidgets.cpp
Parasts fails
@ -0,0 +1,187 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "annotationwidgets.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QMutex>
|
||||
#include <QUrl>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
#include <poppler-qt5.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <poppler-qt4.h>
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
#include <poppler-annotation.h>
|
||||
|
||||
#ifndef HAS_POPPLER_24
|
||||
|
||||
#define LOCK_ANNOTATION QMutexLocker mutexLocker(m_mutex);
|
||||
|
||||
#else
|
||||
|
||||
#define LOCK_ANNOTATION
|
||||
|
||||
#endif // HAS_POPPLER_24
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool hideOnEscape(QWidget* widget, QKeyEvent* event)
|
||||
{
|
||||
if(event->key() == Qt::Key_Escape)
|
||||
{
|
||||
widget->hide();
|
||||
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
AnnotationWidget::AnnotationWidget(QMutex* mutex, Poppler::Annotation* annotation, QWidget* parent) : QPlainTextEdit(parent),
|
||||
m_mutex(mutex),
|
||||
m_annotation(annotation)
|
||||
{
|
||||
LOCK_ANNOTATION
|
||||
|
||||
setTabChangesFocus(true);
|
||||
setPlainText(m_annotation->contents());
|
||||
|
||||
connect(this, SIGNAL(textChanged()), SLOT(on_textChanged()));
|
||||
connect(this, SIGNAL(textChanged()), SIGNAL(wasModified()));
|
||||
|
||||
moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
void AnnotationWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(!hideOnEscape(this, event))
|
||||
{
|
||||
QPlainTextEdit::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationWidget::on_textChanged()
|
||||
{
|
||||
LOCK_ANNOTATION
|
||||
|
||||
m_annotation->setContents(toPlainText());
|
||||
}
|
||||
|
||||
|
||||
FileAttachmentAnnotationWidget::FileAttachmentAnnotationWidget(QMutex* mutex, Poppler::FileAttachmentAnnotation* annotation, QWidget* parent) : QToolButton(parent),
|
||||
m_mutex(mutex),
|
||||
m_annotation(annotation)
|
||||
{
|
||||
m_menu = new QMenu(this);
|
||||
m_saveAction = m_menu->addAction(tr("Save..."));
|
||||
m_saveAndOpenAction = m_menu->addAction(tr("Save and open..."));
|
||||
|
||||
setMenu(m_menu);
|
||||
setPopupMode(QToolButton::InstantPopup);
|
||||
setIcon(QIcon::fromTheme(QLatin1String("mail-attachment"), QIcon(QLatin1String(":icons/mail-attachment"))));
|
||||
|
||||
connect(m_menu, SIGNAL(aboutToShow()), SLOT(on_aboutToShow()));
|
||||
connect(m_menu, SIGNAL(aboutToHide()), SLOT(on_aboutToHide()));
|
||||
|
||||
connect(m_saveAction, SIGNAL(triggered()), SLOT(on_save_triggered()));
|
||||
connect(m_saveAndOpenAction, SIGNAL(triggered()), SLOT(on_saveAndOpen_triggered()));
|
||||
}
|
||||
|
||||
void FileAttachmentAnnotationWidget::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if(!hideOnEscape(this, event))
|
||||
{
|
||||
QToolButton::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void FileAttachmentAnnotationWidget::on_aboutToShow()
|
||||
{
|
||||
graphicsProxyWidget()->setZValue(1.0);
|
||||
}
|
||||
|
||||
void FileAttachmentAnnotationWidget::on_aboutToHide()
|
||||
{
|
||||
graphicsProxyWidget()->setZValue(0.0);
|
||||
}
|
||||
|
||||
void FileAttachmentAnnotationWidget::on_save_triggered()
|
||||
{
|
||||
save(false);
|
||||
}
|
||||
|
||||
void FileAttachmentAnnotationWidget::on_saveAndOpen_triggered()
|
||||
{
|
||||
save(true);
|
||||
}
|
||||
|
||||
void FileAttachmentAnnotationWidget::save(bool open)
|
||||
{
|
||||
LOCK_ANNOTATION
|
||||
|
||||
Poppler::EmbeddedFile* embeddedFile = m_annotation->embeddedFile();
|
||||
|
||||
QString filePath = QFileDialog::getSaveFileName(0, tr("Save file attachment"), embeddedFile->name());
|
||||
|
||||
if(!filePath.isEmpty())
|
||||
{
|
||||
QFile file(filePath);
|
||||
|
||||
if(file.open(QIODevice::WriteOnly | QIODevice::Truncate))
|
||||
{
|
||||
file.write(embeddedFile->data());
|
||||
|
||||
file.close();
|
||||
|
||||
if(open)
|
||||
{
|
||||
if(!QDesktopServices::openUrl(QUrl::fromLocalFile(filePath)))
|
||||
{
|
||||
QMessageBox::warning(0, tr("Warning"), tr("Could not open file attachment saved to '%1'.").arg(filePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(0, tr("Warning"), tr("Could not save file attachment to '%1'.").arg(filePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // qpdfview
|
97
sources/annotationwidgets.h
Parasts fails
97
sources/annotationwidgets.h
Parasts fails
@ -0,0 +1,97 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ANNOTATIONWIDGETS_H
|
||||
#define ANNOTATIONWIDGETS_H
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
#include <QToolButton>
|
||||
|
||||
class QMutex;
|
||||
|
||||
namespace Poppler
|
||||
{
|
||||
class Annotation;
|
||||
class FileAttachmentAnnotation;
|
||||
}
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class AnnotationWidget : public QPlainTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AnnotationWidget(QMutex* mutex, Poppler::Annotation* annotation, QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
protected slots:
|
||||
void on_textChanged();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(AnnotationWidget)
|
||||
|
||||
QMutex* m_mutex;
|
||||
Poppler::Annotation* m_annotation;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class FileAttachmentAnnotationWidget : public QToolButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FileAttachmentAnnotationWidget(QMutex* mutex, Poppler::FileAttachmentAnnotation* annotation, QWidget* parent = 0);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
protected slots:
|
||||
void on_aboutToShow();
|
||||
void on_aboutToHide();
|
||||
|
||||
void on_save_triggered();
|
||||
void on_saveAndOpen_triggered();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(FileAttachmentAnnotationWidget)
|
||||
|
||||
QMutex* m_mutex;
|
||||
Poppler::FileAttachmentAnnotation* m_annotation;
|
||||
|
||||
void save(bool open = false);
|
||||
|
||||
QMenu* m_menu;
|
||||
QAction* m_saveAction;
|
||||
QAction* m_saveAndOpenAction;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // ANNOTATIONWIDGETS_H
|
88
sources/bookmarkdialog.cpp
Parasts fails
88
sources/bookmarkdialog.cpp
Parasts fails
@ -0,0 +1,88 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "bookmarkdialog.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QTextEdit>
|
||||
|
||||
#include "global.h"
|
||||
#include "bookmarkmodel.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
BookmarkDialog::BookmarkDialog(BookmarkItem& bookmark, QWidget* parent) : QDialog(parent),
|
||||
m_bookmark(bookmark)
|
||||
{
|
||||
setWindowTitle(tr("Bookmark"));
|
||||
|
||||
QFormLayout* formLayout = new QFormLayout(this);
|
||||
setLayout(formLayout);
|
||||
|
||||
m_pageEdit = new QLineEdit(this);
|
||||
m_pageEdit->setReadOnly(true);
|
||||
m_pageEdit->setText(QString::number(m_bookmark.page));
|
||||
|
||||
formLayout->addRow(tr("Page:"), m_pageEdit);
|
||||
|
||||
m_labelEdit = new QLineEdit(this);
|
||||
m_labelEdit->setText(m_bookmark.label);
|
||||
|
||||
formLayout->addRow(tr("Label:"), m_labelEdit);
|
||||
|
||||
m_commentEdit = new QTextEdit(this);
|
||||
m_commentEdit->setPlainText(m_bookmark.comment);
|
||||
|
||||
formLayout->addRow(tr("Comment:"), m_commentEdit);
|
||||
|
||||
m_modifiedEdit = new QLineEdit(this);
|
||||
m_modifiedEdit->setReadOnly(true);
|
||||
m_modifiedEdit->setText(m_bookmark.modified.toString(Qt::SystemLocaleLongDate));
|
||||
|
||||
formLayout->addRow(tr("Modified:"), m_modifiedEdit);
|
||||
|
||||
m_dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
|
||||
connect(m_dialogButtonBox, SIGNAL(accepted()), SLOT(accept()));
|
||||
connect(m_dialogButtonBox, SIGNAL(rejected()), SLOT(reject()));
|
||||
|
||||
formLayout->addWidget(m_dialogButtonBox);
|
||||
}
|
||||
|
||||
void BookmarkDialog::accept()
|
||||
{
|
||||
QDialog::accept();
|
||||
|
||||
m_bookmark.label = m_labelEdit->text();
|
||||
m_bookmark.comment = m_commentEdit->toPlainText();
|
||||
|
||||
m_bookmark.modified = QDateTime::currentDateTime();
|
||||
}
|
||||
|
||||
void BookmarkDialog::showEvent(QShowEvent*)
|
||||
{
|
||||
m_labelEdit->setFocus();
|
||||
}
|
||||
|
||||
} // qpdfview
|
65
sources/bookmarkdialog.h
Parasts fails
65
sources/bookmarkdialog.h
Parasts fails
@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOKMARKDIALOG_H
|
||||
#define BOOKMARKDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QDialogButtonBox;
|
||||
class QLineEdit;
|
||||
class QTextEdit;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
struct BookmarkItem;
|
||||
|
||||
class BookmarkDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BookmarkDialog(BookmarkItem& bookmark, QWidget* parent = 0);
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent*);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(BookmarkDialog)
|
||||
|
||||
BookmarkItem& m_bookmark;
|
||||
|
||||
QLineEdit* m_pageEdit;
|
||||
QLineEdit* m_labelEdit;
|
||||
QTextEdit* m_commentEdit;
|
||||
QLineEdit* m_modifiedEdit;
|
||||
|
||||
QDialogButtonBox* m_dialogButtonBox;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // BOOKMARKDIALOG_H
|
122
sources/bookmarkmenu.cpp
Parasts fails
122
sources/bookmarkmenu.cpp
Parasts fails
@ -0,0 +1,122 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2012-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "bookmarkmenu.h"
|
||||
|
||||
#include "miscellaneous.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
BookmarkMenu::BookmarkMenu(const QFileInfo& fileInfo, QWidget* parent) : QMenu(parent)
|
||||
{
|
||||
QAction* const action = menuAction();
|
||||
|
||||
action->setText(fileInfo.completeBaseName());
|
||||
action->setToolTip(fileInfo.absoluteFilePath());
|
||||
|
||||
action->setData(fileInfo.absoluteFilePath());
|
||||
|
||||
m_openAction = addAction(tr("&Open"));
|
||||
m_openAction->setIcon(loadIconWithFallback(QLatin1String("document-open")));
|
||||
m_openAction->setIconVisibleInMenu(true);
|
||||
connect(m_openAction, SIGNAL(triggered()), SLOT(on_open_triggered()));
|
||||
|
||||
m_openInNewTabAction = addAction(tr("Open in new &tab"));
|
||||
m_openInNewTabAction->setIcon(loadIconWithFallback(QLatin1String("tab-new")));
|
||||
m_openInNewTabAction->setIconVisibleInMenu(true);
|
||||
connect(m_openInNewTabAction, SIGNAL(triggered()), SLOT(on_openInNewTab_triggered()));
|
||||
|
||||
m_jumpToPageActionGroup = new QActionGroup(this);
|
||||
connect(m_jumpToPageActionGroup, SIGNAL(triggered(QAction*)), SLOT(on_jumpToPage_triggered(QAction*)));
|
||||
|
||||
m_separatorAction = addSeparator();
|
||||
|
||||
m_removeBookmarkAction = addAction(tr("&Remove bookmark"));
|
||||
connect(m_removeBookmarkAction, SIGNAL(triggered()), SLOT(on_removeBookmark_triggered()));
|
||||
}
|
||||
|
||||
void BookmarkMenu::addJumpToPageAction(int page, const QString& label)
|
||||
{
|
||||
QAction* before = m_separatorAction;
|
||||
|
||||
foreach(QAction* action, m_jumpToPageActionGroup->actions())
|
||||
{
|
||||
if(action->data().toInt() == page)
|
||||
{
|
||||
action->setText(label);
|
||||
|
||||
return;
|
||||
}
|
||||
else if(action->data().toInt() > page)
|
||||
{
|
||||
before = action;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QAction* action = new QAction(label, this);
|
||||
action->setIcon(loadIconWithFallback(QLatin1String("go-jump")));
|
||||
action->setIconVisibleInMenu(true);
|
||||
action->setData(page);
|
||||
|
||||
insertAction(before, action);
|
||||
m_jumpToPageActionGroup->addAction(action);
|
||||
}
|
||||
|
||||
void BookmarkMenu::removeJumpToPageAction(int page)
|
||||
{
|
||||
foreach(QAction* action, m_jumpToPageActionGroup->actions())
|
||||
{
|
||||
if(action->data().toInt() == page)
|
||||
{
|
||||
delete action;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkMenu::on_open_triggered()
|
||||
{
|
||||
emit openTriggered(absoluteFilePath());
|
||||
}
|
||||
|
||||
void BookmarkMenu::on_openInNewTab_triggered()
|
||||
{
|
||||
emit openInNewTabTriggered(absoluteFilePath());
|
||||
}
|
||||
|
||||
void BookmarkMenu::on_jumpToPage_triggered(QAction* action)
|
||||
{
|
||||
emit jumpToPageTriggered(absoluteFilePath(), action->data().toInt());
|
||||
}
|
||||
|
||||
void BookmarkMenu::on_removeBookmark_triggered()
|
||||
{
|
||||
emit removeBookmarkTriggered(absoluteFilePath());
|
||||
}
|
||||
|
||||
} // qpdfview
|
74
sources/bookmarkmenu.h
Parasts fails
74
sources/bookmarkmenu.h
Parasts fails
@ -0,0 +1,74 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2012-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOKMARKMENU_H
|
||||
#define BOOKMARKMENU_H
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
#include <QPair>
|
||||
|
||||
class QFileInfo;
|
||||
|
||||
#include "global.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class BookmarkMenu : public QMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BookmarkMenu(const QFileInfo& fileInfo, QWidget* parent = 0);
|
||||
|
||||
QString absoluteFilePath() const { return menuAction()->data().toString(); }
|
||||
|
||||
void addJumpToPageAction(int page, const QString& label);
|
||||
void removeJumpToPageAction(int page);
|
||||
|
||||
signals:
|
||||
void openTriggered(const QString& filePath);
|
||||
void openInNewTabTriggered(const QString& filePath);
|
||||
void jumpToPageTriggered(const QString& filePath, int page);
|
||||
void removeBookmarkTriggered(const QString& filePath);
|
||||
|
||||
protected slots:
|
||||
void on_open_triggered();
|
||||
void on_openInNewTab_triggered();
|
||||
void on_jumpToPage_triggered(QAction* action);
|
||||
void on_removeBookmark_triggered();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(BookmarkMenu)
|
||||
|
||||
QAction* m_openAction;
|
||||
QAction* m_openInNewTabAction;
|
||||
QActionGroup* m_jumpToPageActionGroup;
|
||||
QAction* m_separatorAction;
|
||||
QAction* m_removeBookmarkAction;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // BOOKMARKMENU_H
|
160
sources/bookmarkmodel.cpp
Parasts fails
160
sources/bookmarkmodel.cpp
Parasts fails
@ -0,0 +1,160 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 S. Razi Alavizadeh
|
||||
Copyright 2014-2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "bookmarkmodel.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
static inline bool operator<(int page, const BookmarkItem& bookmark) { return page < bookmark.page; }
|
||||
static inline bool operator<(const BookmarkItem& bookmark, int page) { return bookmark.page < page; }
|
||||
|
||||
QHash< QString, BookmarkModel* > BookmarkModel::s_instances;
|
||||
|
||||
BookmarkModel* BookmarkModel::fromPath(const QString& path, bool create)
|
||||
{
|
||||
BookmarkModel* model = s_instances.value(path, 0);
|
||||
|
||||
if(create && model == 0)
|
||||
{
|
||||
model = new BookmarkModel(qApp);
|
||||
|
||||
s_instances.insert(path, model);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
QList< QString > BookmarkModel::paths()
|
||||
{
|
||||
return s_instances.keys();
|
||||
}
|
||||
|
||||
void BookmarkModel::removePath(const QString& path)
|
||||
{
|
||||
delete s_instances.take(path);
|
||||
}
|
||||
|
||||
void BookmarkModel::removeAllPaths()
|
||||
{
|
||||
qDeleteAll(s_instances);
|
||||
s_instances.clear();
|
||||
}
|
||||
|
||||
void BookmarkModel::addBookmark(const BookmarkItem& bookmark)
|
||||
{
|
||||
const QVector< BookmarkItem >::iterator at = qLowerBound(m_bookmarks.begin(), m_bookmarks.end(), bookmark.page);
|
||||
const int row = at - m_bookmarks.begin();
|
||||
|
||||
if(at != m_bookmarks.end() && at->page == bookmark.page)
|
||||
{
|
||||
*at = bookmark;
|
||||
|
||||
emit dataChanged(createIndex(row, 0), createIndex(row, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
|
||||
m_bookmarks.insert(at, bookmark);
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkModel::removeBookmark(const BookmarkItem& bookmark)
|
||||
{
|
||||
const QVector< BookmarkItem >::iterator at = qBinaryFind(m_bookmarks.begin(), m_bookmarks.end(), bookmark.page);
|
||||
const int row = at - m_bookmarks.begin();
|
||||
|
||||
if(at != m_bookmarks.end())
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
|
||||
m_bookmarks.erase(at);
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkModel::findBookmark(BookmarkItem& bookmark) const
|
||||
{
|
||||
const QVector< BookmarkItem >::const_iterator at = qBinaryFind(m_bookmarks.constBegin(), m_bookmarks.constEnd(), bookmark.page);
|
||||
|
||||
if(at != m_bookmarks.constEnd())
|
||||
{
|
||||
bookmark = *at;
|
||||
}
|
||||
}
|
||||
|
||||
Qt::ItemFlags BookmarkModel::flags(const QModelIndex&) const
|
||||
{
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
int BookmarkModel::columnCount(const QModelIndex&) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
int BookmarkModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return !parent.isValid() ? m_bookmarks.count() : 0;
|
||||
}
|
||||
|
||||
QVariant BookmarkModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if(!index.isValid() || index.row() >= m_bookmarks.count())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const BookmarkItem& bookmark = m_bookmarks.at(index.row());
|
||||
|
||||
switch(role)
|
||||
{
|
||||
default:
|
||||
return QVariant();
|
||||
case PageRole:
|
||||
return bookmark.page;
|
||||
case LabelRole:
|
||||
case Qt::DisplayRole:
|
||||
return index.column() == 0 ? bookmark.label : QString::number(bookmark.page);
|
||||
case CommentRole:
|
||||
return bookmark.comment;
|
||||
case Qt::ToolTipRole:
|
||||
return QString("<p>%1</p>").arg(bookmark.comment);
|
||||
case ModifiedRole:
|
||||
return bookmark.modified;
|
||||
case Qt::TextAlignmentRole:
|
||||
return index.column() == 0 ? Qt::AlignLeft : Qt::AlignRight;
|
||||
}
|
||||
}
|
||||
|
||||
BookmarkModel::BookmarkModel(QObject* parent) : QAbstractListModel(parent),
|
||||
m_bookmarks()
|
||||
{
|
||||
}
|
||||
|
||||
} // qpdfview
|
105
sources/bookmarkmodel.h
Parasts fails
105
sources/bookmarkmodel.h
Parasts fails
@ -0,0 +1,105 @@
|
||||
/*
|
||||
|
||||
Copyright 2014-2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOKMARKMODEL_H
|
||||
#define BOOKMARKMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QHash>
|
||||
#include <QVector>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
struct BookmarkItem
|
||||
{
|
||||
int page;
|
||||
|
||||
QString label;
|
||||
QString comment;
|
||||
QDateTime modified;
|
||||
|
||||
BookmarkItem(int page = -1, const QString& label = QString(), const QString& comment = QString(), const QDateTime& modified = QDateTime::currentDateTime()) :
|
||||
page(page),
|
||||
label(label),
|
||||
comment(comment),
|
||||
modified(modified) {}
|
||||
|
||||
};
|
||||
|
||||
} // namespace qpdfview
|
||||
|
||||
Q_DECLARE_TYPEINFO(qpdfview::BookmarkItem, Q_MOVABLE_TYPE);
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class BookmarkModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static BookmarkModel* fromPath(const QString& path, bool create = false);
|
||||
|
||||
static QList< QString > paths();
|
||||
|
||||
static void removePath(const QString& path);
|
||||
static void removeAllPaths();
|
||||
|
||||
|
||||
bool isEmpty() const { return m_bookmarks.isEmpty(); }
|
||||
|
||||
void addBookmark(const BookmarkItem& bookmark);
|
||||
void removeBookmark(const BookmarkItem& bookmark);
|
||||
|
||||
void findBookmark(BookmarkItem& bookmark) const;
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
PageRole = Qt::UserRole + 1,
|
||||
LabelRole,
|
||||
CommentRole,
|
||||
ModifiedRole
|
||||
};
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex&) const;
|
||||
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(BookmarkModel)
|
||||
|
||||
static QHash< QString, BookmarkModel* > s_instances;
|
||||
BookmarkModel(QObject* parent = 0);
|
||||
|
||||
QVector< BookmarkItem > m_bookmarks;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // BOOKMARKMODEL_H
|
1113
sources/database.cpp
Parasts fails
1113
sources/database.cpp
Parasts fails
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
108
sources/database.h
Parasts fails
108
sources/database.h
Parasts fails
@ -0,0 +1,108 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2013-2018 Adam Reichold
|
||||
Copyright 2018 Egor Zenkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DATABASE_H
|
||||
#define DATABASE_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#ifdef WITH_SQL
|
||||
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#endif // WITH_SQL
|
||||
|
||||
class QDateTime;
|
||||
|
||||
#include "global.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class DocumentView;
|
||||
|
||||
class Database : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static Database* instance();
|
||||
~Database();
|
||||
|
||||
QStringList knownInstanceNames();
|
||||
|
||||
struct RestoreTab
|
||||
{
|
||||
virtual DocumentView* operator()(const QString& absoluteFilePath) const = 0;
|
||||
};
|
||||
|
||||
void restoreTabs(const RestoreTab& restoreTab);
|
||||
void saveTabs(const QVector< DocumentView* >& tabs);
|
||||
void clearTabs();
|
||||
|
||||
void restoreBookmarks();
|
||||
void saveBookmarks();
|
||||
void clearBookmarks();
|
||||
|
||||
void restorePerFileSettings(DocumentView* tab);
|
||||
void savePerFileSettings(const DocumentView* tab);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Database)
|
||||
|
||||
static Database* s_instance;
|
||||
Database(QObject* parent = 0);
|
||||
|
||||
static QString instanceName();
|
||||
|
||||
#ifdef WITH_SQL
|
||||
|
||||
bool prepareTabs_v5();
|
||||
bool prepareBookmarks_v3();
|
||||
bool preparePerFileSettings_v4();
|
||||
bool preparePerFileSettings_Outline_v1();
|
||||
|
||||
void migrateTabs_v4_v5();
|
||||
void migrateTabs_v3_v5();
|
||||
void migrateTabs_v2_v5();
|
||||
void migrateTabs_v1_v5();
|
||||
void migrateBookmarks_v2_v3();
|
||||
void migrateBookmarks_v1_v3();
|
||||
void migratePerFileSettings_v3_v4();
|
||||
void migratePerFileSettings_v2_v4();
|
||||
void migratePerFileSettings_v1_v4();
|
||||
|
||||
bool prepareTable(const QString& prepare);
|
||||
void migrateTable(const QString& migrate, const QString& prune, const QString& warning);
|
||||
|
||||
void limitPerFileSettings();
|
||||
|
||||
QSqlDatabase m_database;
|
||||
|
||||
#endif // WITH_SQL
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // DATABASE_H
|
1003
sources/djvumodel.cpp
Parasts fails
1003
sources/djvumodel.cpp
Parasts fails
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
140
sources/djvumodel.h
Parasts fails
140
sources/djvumodel.h
Parasts fails
@ -0,0 +1,140 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Adam Reichold
|
||||
Copyright 2013 Alexander Volkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
The implementation is based on KDjVu by Pino Toscano.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DJVUMODEL_H
|
||||
#define DJVUMODEL_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QMutex>
|
||||
|
||||
typedef struct ddjvu_context_s ddjvu_context_t;
|
||||
typedef struct ddjvu_format_s ddjvu_format_t;
|
||||
typedef struct ddjvu_document_s ddjvu_document_t;
|
||||
typedef struct ddjvu_pageinfo_s ddjvu_pageinfo_t;
|
||||
|
||||
#include "model.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class DjVuPlugin;
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class DjVuPage : public Page
|
||||
{
|
||||
friend class DjVuDocument;
|
||||
|
||||
public:
|
||||
~DjVuPage();
|
||||
|
||||
QSizeF size() const;
|
||||
|
||||
QImage render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const;
|
||||
|
||||
QString label() const;
|
||||
|
||||
QList< Link* > links() const;
|
||||
|
||||
QString text(const QRectF& rect) const;
|
||||
|
||||
QList< QRectF > search(const QString& text, bool matchCase, bool wholeWords) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(DjVuPage)
|
||||
|
||||
DjVuPage(const class DjVuDocument* parent, int index, const ddjvu_pageinfo_t& pageinfo);
|
||||
|
||||
const class DjVuDocument* m_parent;
|
||||
|
||||
int m_index;
|
||||
QSizeF m_size;
|
||||
int m_resolution;
|
||||
|
||||
};
|
||||
|
||||
class DjVuDocument : public Document
|
||||
{
|
||||
friend class DjVuPage;
|
||||
friend class qpdfview::DjVuPlugin;
|
||||
|
||||
public:
|
||||
~DjVuDocument();
|
||||
|
||||
int numberOfPages() const;
|
||||
|
||||
Page* page(int index) const;
|
||||
|
||||
QStringList saveFilter() const;
|
||||
|
||||
bool canSave() const;
|
||||
bool save(const QString& filePath, bool withChanges) const;
|
||||
|
||||
Outline outline() const;
|
||||
Properties properties() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(DjVuDocument)
|
||||
|
||||
DjVuDocument(QMutex* globalMutex, ddjvu_context_t* context, ddjvu_document_t* document);
|
||||
|
||||
mutable QMutex m_mutex;
|
||||
mutable QMutex* m_globalMutex;
|
||||
|
||||
ddjvu_context_t* m_context;
|
||||
ddjvu_document_t* m_document;
|
||||
ddjvu_format_t* m_format;
|
||||
|
||||
QHash< QString, int > m_pageByName;
|
||||
QHash< int, QString > m_titleByIndex;
|
||||
|
||||
void prepareFileInfo();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class DjVuPlugin : public QObject, Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(qpdfview::Plugin)
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
Q_PLUGIN_METADATA(IID "local.qpdfview.Plugin")
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
public:
|
||||
DjVuPlugin(QObject* parent = 0);
|
||||
|
||||
Model::Document* loadDocument(const QString& filePath) const;
|
||||
|
||||
private:
|
||||
mutable QMutex m_globalMutex;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // DJVUMODEL_H
|
362
sources/documentlayout.cpp
Parasts fails
362
sources/documentlayout.cpp
Parasts fails
@ -0,0 +1,362 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2013-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "documentlayout.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "pageitem.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace qpdfview;
|
||||
|
||||
const qreal viewportPadding = 6.0f;
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
Settings* DocumentLayout::s_settings = 0;
|
||||
|
||||
DocumentLayout::DocumentLayout()
|
||||
{
|
||||
if(s_settings == 0)
|
||||
{
|
||||
s_settings = Settings::instance();
|
||||
}
|
||||
}
|
||||
|
||||
DocumentLayout* DocumentLayout::fromLayoutMode(LayoutMode layoutMode)
|
||||
{
|
||||
switch(layoutMode)
|
||||
{
|
||||
default:
|
||||
case SinglePageMode: return new SinglePageLayout;
|
||||
case TwoPagesMode: return new TwoPagesLayout;
|
||||
case TwoPagesWithCoverPageMode: return new TwoPagesWithCoverPageLayout;
|
||||
case MultiplePagesMode: return new MultiplePagesLayout;
|
||||
}
|
||||
}
|
||||
|
||||
bool DocumentLayout::isCurrentPage(const QRectF& visibleRect, const QRectF& pageRect) const
|
||||
{
|
||||
// Works with vertically scrolling layouts, i.e. all currently implemented layouts.
|
||||
const qreal pageVisibleHeight = pageRect.intersected(visibleRect).height();
|
||||
const qreal pageTopOffset = pageRect.top() - visibleRect.top();
|
||||
|
||||
if(visibleRect.height() > 2.0f * pageRect.height()) // Are more than two pages visible?
|
||||
{
|
||||
const qreal halfPageHeight = 0.5f * pageRect.height();
|
||||
|
||||
return pageVisibleHeight >= halfPageHeight && pageTopOffset < halfPageHeight && pageTopOffset >= -halfPageHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pageVisibleHeight >= 0.5f * visibleRect.height();
|
||||
}
|
||||
}
|
||||
|
||||
qreal DocumentLayout::visibleHeight(int viewportHeight) const
|
||||
{
|
||||
const qreal pageSpacing = s_settings->documentView().pageSpacing();
|
||||
|
||||
return viewportHeight - 2.0f * pageSpacing;
|
||||
}
|
||||
|
||||
|
||||
int SinglePageLayout::currentPage(int page) const
|
||||
{
|
||||
return page;
|
||||
}
|
||||
|
||||
int SinglePageLayout::previousPage(int page) const
|
||||
{
|
||||
return qMax(page - 1, 1);
|
||||
}
|
||||
|
||||
int SinglePageLayout::nextPage(int page, int count) const
|
||||
{
|
||||
return qMin(page + 1, count);
|
||||
}
|
||||
|
||||
QPair< int, int > SinglePageLayout::prefetchRange(int page, int count) const
|
||||
{
|
||||
const int prefetchDistance = s_settings->documentView().prefetchDistance();
|
||||
|
||||
return qMakePair(qMax(page - prefetchDistance / 2, 1),
|
||||
qMin(page + prefetchDistance, count));
|
||||
}
|
||||
|
||||
int SinglePageLayout::leftIndex(int index) const
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
int SinglePageLayout::rightIndex(int index, int count) const
|
||||
{
|
||||
Q_UNUSED(count);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
qreal SinglePageLayout::visibleWidth(int viewportWidth) const
|
||||
{
|
||||
const qreal pageSpacing = s_settings->documentView().pageSpacing();
|
||||
|
||||
return viewportWidth - viewportPadding - 2.0f * pageSpacing;
|
||||
}
|
||||
|
||||
void SinglePageLayout::prepareLayout(const QVector< PageItem* >& pageItems, bool /* rightToLeft */,
|
||||
qreal& left, qreal& right, qreal& height)
|
||||
{
|
||||
const qreal pageSpacing = s_settings->documentView().pageSpacing();
|
||||
qreal pageHeight = 0.0f;
|
||||
|
||||
for(int index = 0; index < pageItems.count(); ++index)
|
||||
{
|
||||
PageItem* page = pageItems.at(index);
|
||||
const QRectF boundingRect = page->boundingRect();
|
||||
|
||||
page->setPos(-boundingRect.left() - 0.5f * boundingRect.width(), height - boundingRect.top());
|
||||
|
||||
pageHeight = boundingRect.height();
|
||||
|
||||
left = qMin(left, -0.5f * boundingRect.width() - pageSpacing);
|
||||
right = qMax(right, 0.5f * boundingRect.width() + pageSpacing);
|
||||
height += pageHeight + pageSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int TwoPagesLayout::currentPage(int page) const
|
||||
{
|
||||
return page % 2 != 0 ? page : page - 1;
|
||||
}
|
||||
|
||||
int TwoPagesLayout::previousPage(int page) const
|
||||
{
|
||||
return qMax(page - 2, 1);
|
||||
}
|
||||
|
||||
int TwoPagesLayout::nextPage(int page, int count) const
|
||||
{
|
||||
return qMin(page + 2, count);
|
||||
}
|
||||
|
||||
QPair< int, int > TwoPagesLayout::prefetchRange(int page, int count) const
|
||||
{
|
||||
const int prefetchDistance = s_settings->documentView().prefetchDistance();
|
||||
|
||||
return qMakePair(qMax(page - prefetchDistance, 1),
|
||||
qMin(page + 2 * prefetchDistance + 1, count));
|
||||
}
|
||||
|
||||
int TwoPagesLayout::leftIndex(int index) const
|
||||
{
|
||||
return index % 2 == 0 ? index : index - 1;
|
||||
}
|
||||
|
||||
int TwoPagesLayout::rightIndex(int index, int count) const
|
||||
{
|
||||
return qMin(index % 2 == 0 ? index + 1 : index, count - 1);
|
||||
}
|
||||
|
||||
qreal TwoPagesLayout::visibleWidth(int viewportWidth) const
|
||||
{
|
||||
const qreal pageSpacing = s_settings->documentView().pageSpacing();
|
||||
|
||||
return (viewportWidth - viewportPadding - 3.0f * pageSpacing) / 2.0f;
|
||||
}
|
||||
|
||||
void TwoPagesLayout::prepareLayout(const QVector< PageItem* >& pageItems, bool rightToLeft,
|
||||
qreal& left, qreal& right, qreal& height)
|
||||
{
|
||||
const qreal pageSpacing = s_settings->documentView().pageSpacing();
|
||||
qreal pageHeight = 0.0f;
|
||||
|
||||
for(int index = 0; index < pageItems.count(); ++index)
|
||||
{
|
||||
PageItem* page = pageItems.at(index);
|
||||
const QRectF boundingRect = page->boundingRect();
|
||||
|
||||
const qreal leftPos = -boundingRect.left() - boundingRect.width() - 0.5f * pageSpacing;
|
||||
const qreal rightPos = -boundingRect.left() + 0.5f * pageSpacing;
|
||||
|
||||
if(index == leftIndex(index))
|
||||
{
|
||||
page->setPos(rightToLeft ? rightPos : leftPos, height - boundingRect.top());
|
||||
|
||||
pageHeight = boundingRect.height();
|
||||
|
||||
if(rightToLeft)
|
||||
{
|
||||
right = qMax(right, boundingRect.width() + 1.5f * pageSpacing);
|
||||
}
|
||||
else
|
||||
{
|
||||
left = qMin(left, -boundingRect.width() - 1.5f * pageSpacing);
|
||||
}
|
||||
|
||||
if(index == rightIndex(index, pageItems.count()))
|
||||
{
|
||||
right = qMax(right, 0.5f * pageSpacing);
|
||||
height += pageHeight + pageSpacing;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
page->setPos(rightToLeft ? leftPos : rightPos, height - boundingRect.top());
|
||||
|
||||
pageHeight = qMax(pageHeight, boundingRect.height());
|
||||
|
||||
if(rightToLeft)
|
||||
{
|
||||
left = qMin(left, -boundingRect.width() - 1.5f * pageSpacing);
|
||||
}
|
||||
else
|
||||
{
|
||||
right = qMax(right, boundingRect.width() + 1.5f * pageSpacing);
|
||||
}
|
||||
|
||||
height += pageHeight + pageSpacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int TwoPagesWithCoverPageLayout::currentPage(int page) const
|
||||
{
|
||||
return page == 1 ? page : (page % 2 == 0 ? page : page - 1);
|
||||
}
|
||||
|
||||
int TwoPagesWithCoverPageLayout::leftIndex(int index) const
|
||||
{
|
||||
return index == 0 ? index : (index % 2 != 0 ? index : index - 1);
|
||||
}
|
||||
|
||||
int TwoPagesWithCoverPageLayout::rightIndex(int index, int count) const
|
||||
{
|
||||
return qMin(index % 2 != 0 ? index + 1 : index, count - 1);
|
||||
}
|
||||
|
||||
|
||||
int MultiplePagesLayout::currentPage(int page) const
|
||||
{
|
||||
const int pagesPerRow = s_settings->documentView().pagesPerRow();
|
||||
|
||||
return page - ((page - 1) % pagesPerRow);
|
||||
}
|
||||
|
||||
int MultiplePagesLayout::previousPage(int page) const
|
||||
{
|
||||
const int pagesPerRow = s_settings->documentView().pagesPerRow();
|
||||
|
||||
return qMax(page - pagesPerRow, 1);
|
||||
}
|
||||
|
||||
int MultiplePagesLayout::nextPage(int page, int count) const
|
||||
{
|
||||
const int pagesPerRow = s_settings->documentView().pagesPerRow();
|
||||
|
||||
return qMin(page + pagesPerRow, count);
|
||||
}
|
||||
|
||||
QPair<int, int> MultiplePagesLayout::prefetchRange(int page, int count) const
|
||||
{
|
||||
const int prefetchDistance = s_settings->documentView().prefetchDistance();
|
||||
const int pagesPerRow = s_settings->documentView().pagesPerRow();
|
||||
|
||||
return qMakePair(qMax(page - pagesPerRow * (prefetchDistance / 2), 1),
|
||||
qMin(page + pagesPerRow * (prefetchDistance + 1) - 1, count));
|
||||
}
|
||||
|
||||
int MultiplePagesLayout::leftIndex(int index) const
|
||||
{
|
||||
const int pagesPerRow = s_settings->documentView().pagesPerRow();
|
||||
|
||||
return index - (index % pagesPerRow);
|
||||
}
|
||||
|
||||
int MultiplePagesLayout::rightIndex(int index, int count) const
|
||||
{
|
||||
const int pagesPerRow = s_settings->documentView().pagesPerRow();
|
||||
|
||||
return qMin(index - (index % pagesPerRow) + pagesPerRow - 1, count - 1);
|
||||
}
|
||||
|
||||
qreal MultiplePagesLayout::visibleWidth(int viewportWidth) const
|
||||
{
|
||||
const qreal pageSpacing = s_settings->documentView().pageSpacing();
|
||||
const int pagesPerRow = s_settings->documentView().pagesPerRow();
|
||||
|
||||
return (viewportWidth - viewportPadding - (pagesPerRow + 1) * pageSpacing) / pagesPerRow;
|
||||
}
|
||||
|
||||
void MultiplePagesLayout::prepareLayout(const QVector< PageItem* >& pageItems, bool rightToLeft,
|
||||
qreal& left, qreal& right, qreal& height)
|
||||
{
|
||||
const qreal pageSpacing = s_settings->documentView().pageSpacing();
|
||||
qreal pageHeight = 0.0;
|
||||
|
||||
for(int index = 0; index < pageItems.count(); ++index)
|
||||
{
|
||||
PageItem* page = pageItems.at(index);
|
||||
const QRectF boundingRect = page->boundingRect();
|
||||
|
||||
const qreal leftPos = left - boundingRect.left() + pageSpacing;
|
||||
const qreal rightPos = right - boundingRect.left() - boundingRect.width() - pageSpacing;
|
||||
|
||||
page->setPos(rightToLeft ? rightPos : leftPos, height - boundingRect.top());
|
||||
|
||||
pageHeight = qMax(pageHeight, boundingRect.height());
|
||||
|
||||
if(rightToLeft)
|
||||
{
|
||||
right -= boundingRect.width() + pageSpacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
left += boundingRect.width() + pageSpacing;
|
||||
}
|
||||
|
||||
if(index == rightIndex(index, pageItems.count()))
|
||||
{
|
||||
height += pageHeight + pageSpacing;
|
||||
pageHeight = 0.0f;
|
||||
|
||||
if(rightToLeft)
|
||||
{
|
||||
left = qMin(left, right - pageSpacing);
|
||||
right = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = qMax(right, left + pageSpacing);
|
||||
left = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // qpdfview
|
143
sources/documentlayout.h
Parasts fails
143
sources/documentlayout.h
Parasts fails
@ -0,0 +1,143 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2013-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DOCUMENTLAYOUT_H
|
||||
#define DOCUMENTLAYOUT_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QPair>
|
||||
|
||||
#include "global.h"
|
||||
|
||||
class QRectF;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class Settings;
|
||||
class PageItem;
|
||||
|
||||
struct DocumentLayout
|
||||
{
|
||||
DocumentLayout();
|
||||
virtual ~DocumentLayout() {}
|
||||
|
||||
static DocumentLayout* fromLayoutMode(LayoutMode layoutMode);
|
||||
|
||||
virtual LayoutMode layoutMode() const = 0;
|
||||
|
||||
virtual int currentPage(int page) const = 0;
|
||||
virtual int previousPage(int page) const = 0;
|
||||
virtual int nextPage(int page, int count) const = 0;
|
||||
|
||||
bool isCurrentPage(const QRectF& visibleRect, const QRectF& pageRect) const;
|
||||
|
||||
virtual QPair< int, int > prefetchRange(int page, int count) const = 0;
|
||||
|
||||
virtual int leftIndex(int index) const = 0;
|
||||
virtual int rightIndex(int index, int count) const = 0;
|
||||
|
||||
virtual qreal visibleWidth(int viewportWidth) const = 0;
|
||||
qreal visibleHeight(int viewportHeight) const;
|
||||
|
||||
virtual void prepareLayout(const QVector< PageItem* >& pageItems, bool rightToLeft,
|
||||
qreal& left, qreal& right, qreal& height) = 0;
|
||||
|
||||
protected:
|
||||
static Settings* s_settings;
|
||||
|
||||
};
|
||||
|
||||
struct SinglePageLayout : public DocumentLayout
|
||||
{
|
||||
LayoutMode layoutMode() const { return SinglePageMode; }
|
||||
|
||||
int currentPage(int page) const;
|
||||
int previousPage(int page) const;
|
||||
int nextPage(int page, int count) const;
|
||||
|
||||
QPair< int, int > prefetchRange(int page, int count) const;
|
||||
|
||||
int leftIndex(int index) const;
|
||||
int rightIndex(int index, int count) const;
|
||||
|
||||
qreal visibleWidth(int viewportWidth) const;
|
||||
|
||||
void prepareLayout(const QVector< PageItem* >& pageItems, bool rightToLeft,
|
||||
qreal& left, qreal& right, qreal& height);
|
||||
|
||||
};
|
||||
|
||||
struct TwoPagesLayout : public DocumentLayout
|
||||
{
|
||||
LayoutMode layoutMode() const { return TwoPagesMode; }
|
||||
|
||||
int currentPage(int page) const;
|
||||
int previousPage(int page) const;
|
||||
int nextPage(int page, int count) const;
|
||||
|
||||
QPair< int, int > prefetchRange(int page, int count) const;
|
||||
|
||||
int leftIndex(int index) const;
|
||||
int rightIndex(int index, int count) const;
|
||||
|
||||
qreal visibleWidth(int viewportWidth) const;
|
||||
|
||||
void prepareLayout(const QVector< PageItem* >& pageItems, bool rightToLeft,
|
||||
qreal& left, qreal& right, qreal& height);
|
||||
|
||||
};
|
||||
|
||||
struct TwoPagesWithCoverPageLayout : public TwoPagesLayout
|
||||
{
|
||||
LayoutMode layoutMode() const { return TwoPagesWithCoverPageMode; }
|
||||
|
||||
int currentPage(int page) const;
|
||||
|
||||
int leftIndex(int index) const;
|
||||
int rightIndex(int index, int count) const;
|
||||
|
||||
};
|
||||
|
||||
struct MultiplePagesLayout : public DocumentLayout
|
||||
{
|
||||
LayoutMode layoutMode() const { return MultiplePagesMode; }
|
||||
|
||||
int currentPage(int page) const;
|
||||
int previousPage(int page) const;
|
||||
int nextPage(int page, int count) const;
|
||||
|
||||
QPair< int, int > prefetchRange(int page, int count) const;
|
||||
|
||||
int leftIndex(int index) const;
|
||||
int rightIndex(int index, int count) const;
|
||||
|
||||
qreal visibleWidth(int viewportWidth) const;
|
||||
|
||||
void prepareLayout(const QVector< PageItem* >& pageItems, bool rightToLeft,
|
||||
qreal& left, qreal& right, qreal& height);
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // DOCUMENTLAYOUT_H
|
3109
sources/documentview.cpp
Parasts fails
3109
sources/documentview.cpp
Parasts fails
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
390
sources/documentview.h
Parasts fails
390
sources/documentview.h
Parasts fails
@ -0,0 +1,390 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2012-2014, 2018 Adam Reichold
|
||||
Copyright 2014 Dorian Scholz
|
||||
Copyright 2018 Egor Zenkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DOCUMENTVIEW_H
|
||||
#define DOCUMENTVIEW_H
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QGraphicsView>
|
||||
#include <QMap>
|
||||
#include <QPersistentModelIndex>
|
||||
|
||||
class QDomNode;
|
||||
class QFileSystemWatcher;
|
||||
class QPrinter;
|
||||
class QStandardItemModel;
|
||||
|
||||
#include "renderparam.h"
|
||||
#include "printoptions.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class Annotation;
|
||||
class Page;
|
||||
class Document;
|
||||
}
|
||||
|
||||
class Settings;
|
||||
class PageItem;
|
||||
class ThumbnailItem;
|
||||
class SearchModel;
|
||||
class SearchTask;
|
||||
class PresentationView;
|
||||
class ShortcutHandler;
|
||||
struct DocumentLayout;
|
||||
|
||||
class DocumentView : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DocumentView(QWidget* parent = 0);
|
||||
~DocumentView();
|
||||
|
||||
const QFileInfo& fileInfo() const { return m_fileInfo; }
|
||||
bool wasModified() const { return m_wasModified; }
|
||||
|
||||
int numberOfPages() const { return m_pages.count(); }
|
||||
int currentPage() const { return m_currentPage; }
|
||||
|
||||
bool hasFrontMatter() const { return m_firstPage > 1; }
|
||||
|
||||
int firstPage() const { return m_firstPage; }
|
||||
void setFirstPage(int firstPage);
|
||||
|
||||
QString defaultPageLabelFromNumber(int number) const;
|
||||
QString pageLabelFromNumber(int number) const;
|
||||
int pageNumberFromLabel(const QString& label) const;
|
||||
|
||||
QString title() const;
|
||||
|
||||
static QStringList openFilter();
|
||||
QStringList saveFilter() const;
|
||||
|
||||
bool canSave() const;
|
||||
|
||||
bool continuousMode() const { return m_continuousMode; }
|
||||
void setContinuousMode(bool continuousMode);
|
||||
|
||||
LayoutMode layoutMode() const;
|
||||
void setLayoutMode(LayoutMode layoutMode);
|
||||
|
||||
bool rightToLeftMode() const { return m_rightToLeftMode; }
|
||||
void setRightToLeftMode(bool rightToLeftMode);
|
||||
|
||||
ScaleMode scaleMode() const { return m_scaleMode; }
|
||||
void setScaleMode(ScaleMode scaleMode);
|
||||
|
||||
qreal scaleFactor() const { return m_scaleFactor; }
|
||||
void setScaleFactor(qreal scaleFactor);
|
||||
|
||||
Rotation rotation() const { return m_rotation; }
|
||||
void setRotation(Rotation rotation);
|
||||
|
||||
qpdfview::RenderFlags renderFlags() const { return m_renderFlags; }
|
||||
void setRenderFlags(qpdfview::RenderFlags renderFlags);
|
||||
void setRenderFlag(qpdfview::RenderFlag renderFlag, bool enabled = true);
|
||||
|
||||
bool invertColors() const { return m_renderFlags.testFlag(InvertColors); }
|
||||
void setInvertColors(bool invertColors) { setRenderFlag(InvertColors, invertColors); }
|
||||
|
||||
bool convertToGrayscale() const { return m_renderFlags.testFlag(ConvertToGrayscale); }
|
||||
void setConvertToGrayscale(bool convertToGrayscale) { setRenderFlag(ConvertToGrayscale, convertToGrayscale); }
|
||||
|
||||
bool trimMargins() const { return m_renderFlags.testFlag(TrimMargins); }
|
||||
void setTrimMargins(bool trimMargins) { setRenderFlag(TrimMargins, trimMargins); }
|
||||
|
||||
CompositionMode compositionMode() const;
|
||||
void setCompositionMode(CompositionMode compositionMode);
|
||||
|
||||
bool highlightAll() const { return m_highlightAll; }
|
||||
void setHighlightAll(bool highlightAll);
|
||||
|
||||
RubberBandMode rubberBandMode() const { return m_rubberBandMode; }
|
||||
void setRubberBandMode(RubberBandMode rubberBandMode);
|
||||
|
||||
QSize thumbnailsViewportSize() const { return m_thumbnailsViewportSize; }
|
||||
void setThumbnailsViewportSize(QSize thumbnailsViewportSize);
|
||||
|
||||
Qt::Orientation thumbnailsOrientation() const { return m_thumbnailsOrientation; }
|
||||
void setThumbnailsOrientation(Qt::Orientation thumbnailsOrientation);
|
||||
|
||||
const QVector< ThumbnailItem* >& thumbnailItems() const { return m_thumbnailItems; }
|
||||
QGraphicsScene* thumbnailsScene() const { return m_thumbnailsScene; }
|
||||
|
||||
QAbstractItemModel* outlineModel() const { return m_outlineModel.data(); }
|
||||
QAbstractItemModel* propertiesModel() const { return m_propertiesModel.data(); }
|
||||
|
||||
QSet< QByteArray > saveExpandedPaths() const;
|
||||
void restoreExpandedPaths(const QSet< QByteArray >& expandedPaths);
|
||||
|
||||
QAbstractItemModel* fontsModel() const;
|
||||
|
||||
bool searchWasCanceled() const;
|
||||
int searchProgress() const;
|
||||
|
||||
QString searchText() const;
|
||||
bool searchMatchCase() const;
|
||||
bool searchWholeWords() const;
|
||||
|
||||
QPair< QString, QString > searchContext(int page, const QRectF& rect) const;
|
||||
|
||||
bool hasSearchResults();
|
||||
|
||||
QString resolveFileName(QString fileName) const;
|
||||
QUrl resolveUrl(QUrl url) const;
|
||||
|
||||
struct SourceLink
|
||||
{
|
||||
QString name;
|
||||
int line;
|
||||
int column;
|
||||
|
||||
operator bool() const { return !name.isNull(); }
|
||||
|
||||
};
|
||||
|
||||
SourceLink sourceLink(QPoint pos);
|
||||
void openInSourceEditor(const SourceLink& sourceLink);
|
||||
|
||||
signals:
|
||||
void documentChanged();
|
||||
void documentModified();
|
||||
|
||||
void numberOfPagesChanged(int numberOfPages);
|
||||
void currentPageChanged(int currentPage, bool trackChange = false);
|
||||
|
||||
void canJumpChanged(bool backward, bool forward);
|
||||
|
||||
void continuousModeChanged(bool continuousMode);
|
||||
void layoutModeChanged(LayoutMode layoutMode);
|
||||
void rightToLeftModeChanged(bool rightToLeftMode);
|
||||
void scaleModeChanged(ScaleMode scaleMode);
|
||||
void scaleFactorChanged(qreal scaleFactor);
|
||||
void rotationChanged(Rotation rotation);
|
||||
|
||||
void linkClicked(int page);
|
||||
void linkClicked(bool newTab, const QString& filePath, int page);
|
||||
|
||||
void renderFlagsChanged(qpdfview::RenderFlags renderFlags);
|
||||
|
||||
void invertColorsChanged(bool invertColors);
|
||||
void convertToGrayscaleChanged(bool convertToGrayscale);
|
||||
void trimMarginsChanged(bool trimMargins);
|
||||
|
||||
void compositionModeChanged(CompositionMode compositionMode);
|
||||
|
||||
void highlightAllChanged(bool highlightAll);
|
||||
void rubberBandModeChanged(RubberBandMode rubberBandMode);
|
||||
|
||||
void searchFinished();
|
||||
void searchProgressChanged(int progress);
|
||||
|
||||
public slots:
|
||||
void show();
|
||||
|
||||
bool open(const QString& filePath);
|
||||
bool refresh();
|
||||
bool save(const QString& filePath, bool withChanges);
|
||||
bool print(QPrinter* printer, const PrintOptions& printOptions = PrintOptions());
|
||||
|
||||
void previousPage();
|
||||
void nextPage();
|
||||
void firstPage();
|
||||
void lastPage();
|
||||
|
||||
void jumpToPage(int page, bool trackChange = true, qreal newLeft = qQNaN(), qreal newTop = qQNaN());
|
||||
|
||||
bool canJumpBackward() const;
|
||||
void jumpBackward();
|
||||
|
||||
bool canJumpForward() const;
|
||||
void jumpForward();
|
||||
|
||||
void temporaryHighlight(int page, const QRectF& highlight);
|
||||
|
||||
void startSearch(const QString& text, bool matchCase, bool wholeWords);
|
||||
void cancelSearch();
|
||||
|
||||
void clearResults();
|
||||
|
||||
void findPrevious();
|
||||
void findNext();
|
||||
void findResult(const QModelIndex& index);
|
||||
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
void originalSize();
|
||||
|
||||
void rotateLeft();
|
||||
void rotateRight();
|
||||
|
||||
void startPresentation();
|
||||
|
||||
protected slots:
|
||||
void on_verticalScrollBar_valueChanged();
|
||||
|
||||
void on_autoRefresh_timeout();
|
||||
void on_prefetch_timeout();
|
||||
|
||||
void on_temporaryHighlight_timeout();
|
||||
|
||||
void on_searchTask_progressChanged(int progress);
|
||||
void on_searchTask_resultsReady(int index, const QList< QRectF >& results);
|
||||
|
||||
void on_pages_cropRectChanged();
|
||||
void on_thumbnails_cropRectChanged();
|
||||
|
||||
void on_pages_linkClicked(bool newTab, int page, qreal left, qreal top);
|
||||
void on_pages_linkClicked(bool newTab, const QString& fileName, int page);
|
||||
void on_pages_linkClicked(const QString& url);
|
||||
|
||||
void on_pages_rubberBandFinished();
|
||||
|
||||
void on_pages_zoomToSelection(int page, const QRectF& rect);
|
||||
void on_pages_openInSourceEditor(int page, QPointF pos);
|
||||
|
||||
void on_pages_wasModified();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void wheelEvent(QWheelEvent* event);
|
||||
|
||||
void contextMenuEvent(QContextMenuEvent* event);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(DocumentView)
|
||||
|
||||
static Settings* s_settings;
|
||||
static ShortcutHandler* s_shortcutHandler;
|
||||
|
||||
QFileSystemWatcher* m_autoRefreshWatcher;
|
||||
QTimer* m_autoRefreshTimer;
|
||||
|
||||
QTimer* m_prefetchTimer;
|
||||
|
||||
Model::Document* m_document;
|
||||
QVector< Model::Page* > m_pages;
|
||||
|
||||
QFileInfo m_fileInfo;
|
||||
bool m_wasModified;
|
||||
|
||||
int m_currentPage;
|
||||
int m_firstPage;
|
||||
|
||||
#ifdef WITH_CUPS
|
||||
|
||||
bool printUsingCUPS(QPrinter* printer, const PrintOptions& printOptions, int fromPage, int toPage);
|
||||
|
||||
#endif // WITH_CUPS
|
||||
|
||||
bool printUsingQt(QPrinter* printer, const PrintOptions& printOptions, int fromPage, int toPage);
|
||||
|
||||
struct Position
|
||||
{
|
||||
int page;
|
||||
qreal left;
|
||||
qreal top;
|
||||
|
||||
Position(int page, qreal left, qreal top) : page(page), left(left), top(top) {}
|
||||
|
||||
};
|
||||
|
||||
QList< Position > m_past;
|
||||
QList< Position > m_future;
|
||||
|
||||
void saveLeftAndTop(qreal& left, qreal& top) const;
|
||||
|
||||
QScopedPointer< DocumentLayout > m_layout;
|
||||
|
||||
bool m_continuousMode;
|
||||
bool m_rightToLeftMode;
|
||||
ScaleMode m_scaleMode;
|
||||
qreal m_scaleFactor;
|
||||
Rotation m_rotation;
|
||||
|
||||
qpdfview::RenderFlags m_renderFlags;
|
||||
|
||||
bool m_highlightAll;
|
||||
RubberBandMode m_rubberBandMode;
|
||||
|
||||
QVector< PageItem* > m_pageItems;
|
||||
QVector< ThumbnailItem* > m_thumbnailItems;
|
||||
|
||||
QGraphicsRectItem* m_highlight;
|
||||
|
||||
QSize m_thumbnailsViewportSize;
|
||||
Qt::Orientation m_thumbnailsOrientation;
|
||||
|
||||
QGraphicsScene* m_thumbnailsScene;
|
||||
|
||||
QScopedPointer< QAbstractItemModel > m_outlineModel;
|
||||
QScopedPointer< QAbstractItemModel > m_propertiesModel;
|
||||
|
||||
bool checkDocument(const QString& filePath, Model::Document* document, QVector< Model::Page* >& pages);
|
||||
|
||||
void loadDocumentDefaults();
|
||||
|
||||
void adjustScrollBarPolicy();
|
||||
|
||||
bool m_verticalScrollBarChangedBlocked;
|
||||
|
||||
class VerticalScrollBarChangedBlocker;
|
||||
|
||||
void prepareDocument(Model::Document* document, const QVector< Model::Page* >& pages);
|
||||
void preparePages();
|
||||
void prepareThumbnails();
|
||||
void prepareBackground();
|
||||
|
||||
void prepareScene();
|
||||
void prepareView(qreal newLeft = 0.0, qreal newTop = 0.0, bool forceScroll = true, int scrollToPage = 0);
|
||||
|
||||
void prepareThumbnailsScene();
|
||||
|
||||
void prepareHighlight(int index, const QRectF& highlight);
|
||||
|
||||
// search
|
||||
|
||||
static SearchModel* s_searchModel;
|
||||
|
||||
QPersistentModelIndex m_currentResult;
|
||||
|
||||
SearchTask* m_searchTask;
|
||||
|
||||
void checkResult();
|
||||
void applyResult();
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
Q_DECLARE_METATYPE(qpdfview::DocumentView::SourceLink)
|
||||
|
||||
#endif // DOCUMENTVIEW_H
|
450
sources/fitzmodel.cpp
Parasts fails
450
sources/fitzmodel.cpp
Parasts fails
@ -0,0 +1,450 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 S. Razi Alavizadeh
|
||||
Copyright 2015 Martin Banky
|
||||
Copyright 2014-2015, 2018 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "fitzmodel.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <qmath.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include <mupdf/fitz/stream.h>
|
||||
#include <mupdf/fitz/bidi.h>
|
||||
#include <mupdf/fitz/output.h>
|
||||
#include <mupdf/fitz/display-list.h>
|
||||
#include <mupdf/fitz/document.h>
|
||||
#include <mupdf/fitz/pool.h>
|
||||
#include <mupdf/fitz/structured-text.h>
|
||||
|
||||
typedef struct pdf_document_s pdf_document;
|
||||
|
||||
pdf_document* pdf_specifics(fz_context*, fz_document*);
|
||||
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace qpdfview;
|
||||
using namespace qpdfview::Model;
|
||||
|
||||
QString removeFilePrefix(const char* uri)
|
||||
{
|
||||
QString url = QString::fromUtf8(uri);
|
||||
|
||||
if(url.startsWith("file://", Qt::CaseInsensitive))
|
||||
{
|
||||
url = url.mid(7);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
Outline loadOutline(fz_outline* item)
|
||||
{
|
||||
Outline outline;
|
||||
|
||||
for(; item; item = item->next)
|
||||
{
|
||||
outline.push_back(Section());
|
||||
Section& section = outline.back();
|
||||
section.title = QString::fromUtf8(item->title);
|
||||
|
||||
if(item->page != -1)
|
||||
{
|
||||
section.link.page = item->page + 1;
|
||||
}
|
||||
else if (item->uri != 0)
|
||||
{
|
||||
section.link.urlOrFileName = removeFilePrefix(item->uri);
|
||||
}
|
||||
|
||||
if(fz_outline* childItem = item->down)
|
||||
{
|
||||
section.children = loadOutline(childItem);
|
||||
}
|
||||
}
|
||||
|
||||
return outline;
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
|
||||
FitzPage::FitzPage(const FitzDocument* parent, fz_page* page) :
|
||||
m_parent(parent),
|
||||
m_page(page)
|
||||
{
|
||||
}
|
||||
|
||||
FitzPage::~FitzPage()
|
||||
{
|
||||
fz_drop_page(m_parent->m_context, m_page);
|
||||
}
|
||||
|
||||
QSizeF FitzPage::size() const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_parent->m_mutex);
|
||||
|
||||
fz_rect rect;
|
||||
fz_bound_page(m_parent->m_context, m_page, &rect);
|
||||
|
||||
return QSizeF(rect.x1 - rect.x0, rect.y1 - rect.y0);
|
||||
}
|
||||
|
||||
QImage FitzPage::render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_parent->m_mutex);
|
||||
|
||||
fz_matrix matrix;
|
||||
|
||||
fz_scale(&matrix, horizontalResolution / 72.0f, verticalResolution / 72.0f);
|
||||
|
||||
switch(rotation)
|
||||
{
|
||||
default:
|
||||
case RotateBy0:
|
||||
fz_pre_rotate(&matrix, 0.0);
|
||||
break;
|
||||
case RotateBy90:
|
||||
fz_pre_rotate(&matrix, 90.0);
|
||||
break;
|
||||
case RotateBy180:
|
||||
fz_pre_rotate(&matrix, 180.0);
|
||||
break;
|
||||
case RotateBy270:
|
||||
fz_pre_rotate(&matrix, 270.0);
|
||||
break;
|
||||
}
|
||||
|
||||
fz_rect rect;
|
||||
fz_bound_page(m_parent->m_context, m_page, &rect);
|
||||
fz_transform_rect(&rect, &matrix);
|
||||
|
||||
fz_irect irect;
|
||||
fz_round_rect(&irect, &rect);
|
||||
|
||||
|
||||
fz_context* context = fz_clone_context(m_parent->m_context);
|
||||
fz_display_list* display_list = fz_new_display_list(context, &rect);
|
||||
|
||||
fz_device* device = fz_new_list_device(context, display_list);
|
||||
fz_run_page(m_parent->m_context, m_page, device, &matrix, 0);
|
||||
fz_close_device(m_parent->m_context, device);
|
||||
fz_drop_device(m_parent->m_context, device);
|
||||
|
||||
|
||||
mutexLocker.unlock();
|
||||
|
||||
|
||||
fz_matrix tileMatrix;
|
||||
fz_translate(&tileMatrix, -rect.x0, -rect.y0);
|
||||
|
||||
fz_rect tileRect = fz_infinite_rect;
|
||||
|
||||
int tileWidth = irect.x1 - irect.x0;
|
||||
int tileHeight = irect.y1 - irect.y0;
|
||||
|
||||
if(!boundingRect.isNull())
|
||||
{
|
||||
fz_pre_translate(&tileMatrix, -boundingRect.x(), -boundingRect.y());
|
||||
|
||||
tileRect.x0 = boundingRect.x();
|
||||
tileRect.y0 = boundingRect.y();
|
||||
|
||||
tileRect.x1 = boundingRect.right();
|
||||
tileRect.y1 = boundingRect.bottom();
|
||||
|
||||
tileWidth = boundingRect.width();
|
||||
tileHeight = boundingRect.height();
|
||||
}
|
||||
|
||||
|
||||
QImage image(tileWidth, tileHeight, QImage::Format_RGB32);
|
||||
image.fill(m_parent->m_paperColor);
|
||||
|
||||
fz_pixmap* pixmap = fz_new_pixmap_with_data(context, fz_device_bgr(context), image.width(), image.height(), 0, 1, image.bytesPerLine(), image.bits());
|
||||
|
||||
device = fz_new_draw_device(context, &tileMatrix, pixmap);
|
||||
fz_run_display_list(context, display_list, device, &fz_identity, &tileRect, 0);
|
||||
fz_close_device(context, device);
|
||||
fz_drop_device(context, device);
|
||||
|
||||
fz_drop_pixmap(context, pixmap);
|
||||
fz_drop_display_list(context, display_list);
|
||||
fz_drop_context(context);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
QList< Link* > FitzPage::links() const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_parent->m_mutex);
|
||||
|
||||
QList< Link* > links;
|
||||
|
||||
fz_rect rect;
|
||||
fz_bound_page(m_parent->m_context, m_page, &rect);
|
||||
|
||||
const qreal width = qAbs(rect.x1 - rect.x0);
|
||||
const qreal height = qAbs(rect.y1 - rect.y0);
|
||||
|
||||
fz_link* first_link = fz_load_links(m_parent->m_context, m_page);
|
||||
|
||||
for(fz_link* link = first_link; link != 0; link = link->next)
|
||||
{
|
||||
const QRectF boundary = QRectF(link->rect.x0 / width, link->rect.y0 / height, (link->rect.x1 - link->rect.x0) / width, (link->rect.y1 - link->rect.y0) / height).normalized();
|
||||
|
||||
if (link->uri != 0)
|
||||
{
|
||||
if (fz_is_external_link(m_parent->m_context, link->uri) == 0)
|
||||
{
|
||||
float left;
|
||||
float top;
|
||||
const int page = fz_resolve_link(m_parent->m_context, m_parent->m_document, link->uri, &left, &top);
|
||||
|
||||
if (page != -1)
|
||||
{
|
||||
links.append(new Link(boundary, page + 1, left / width, top / height));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
links.append(new Link(boundary, removeFilePrefix(link->uri)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fz_drop_link(m_parent->m_context, first_link);
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
QString FitzPage::text(const QRectF &rect) const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_parent->m_mutex);
|
||||
|
||||
fz_rect mediaBox;
|
||||
mediaBox.x0 = rect.x();
|
||||
mediaBox.y0 = rect.y();
|
||||
mediaBox.x1 = rect.right();
|
||||
mediaBox.y1 = rect.bottom();
|
||||
|
||||
fz_stext_page* textPage = fz_new_stext_page(m_parent->m_context, &mediaBox);
|
||||
fz_device* device = fz_new_stext_device(m_parent->m_context, textPage, 0);
|
||||
fz_run_page(m_parent->m_context, m_page, device, &fz_identity, 0);
|
||||
fz_close_device(m_parent->m_context, device);
|
||||
fz_drop_device(m_parent->m_context, device);
|
||||
|
||||
fz_point topLeft;
|
||||
topLeft.x = rect.x();
|
||||
topLeft.y = rect.y();
|
||||
|
||||
fz_point bottomRight;
|
||||
bottomRight.x = rect.right();
|
||||
bottomRight.y = rect.bottom();
|
||||
|
||||
char* selection = fz_copy_selection(m_parent->m_context, textPage, topLeft, bottomRight, 0);
|
||||
QString text = QString::fromUtf8(selection);
|
||||
::free(selection);
|
||||
|
||||
fz_drop_stext_page(m_parent->m_context, textPage);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
QList<QRectF> FitzPage::search(const QString& text, bool matchCase, bool wholeWords) const
|
||||
{
|
||||
Q_UNUSED(matchCase);
|
||||
Q_UNUSED(wholeWords);
|
||||
|
||||
QMutexLocker mutexLocker(&m_parent->m_mutex);
|
||||
|
||||
fz_rect rect;
|
||||
fz_bound_page(m_parent->m_context, m_page, &rect);
|
||||
|
||||
fz_stext_page* textPage = fz_new_stext_page(m_parent->m_context, &rect);
|
||||
fz_device* device = fz_new_stext_device(m_parent->m_context, textPage, 0);
|
||||
fz_run_page(m_parent->m_context, m_page, device, &fz_identity, 0);
|
||||
fz_close_device(m_parent->m_context, device);
|
||||
fz_drop_device(m_parent->m_context, device);
|
||||
|
||||
const QByteArray needle = text.toUtf8();
|
||||
|
||||
QVector< fz_rect > hits(32);
|
||||
int numberOfHits = fz_search_stext_page(m_parent->m_context, textPage, needle.constData(), hits.data(), hits.size());
|
||||
|
||||
while(numberOfHits == hits.size())
|
||||
{
|
||||
hits.resize(2 * hits.size());
|
||||
numberOfHits = fz_search_stext_page(m_parent->m_context, textPage, needle.constData(), hits.data(), hits.size());
|
||||
}
|
||||
|
||||
hits.resize(numberOfHits);
|
||||
|
||||
fz_drop_stext_page(m_parent->m_context, textPage);
|
||||
|
||||
QList< QRectF > results;
|
||||
results.reserve(hits.size());
|
||||
|
||||
foreach(fz_rect rect, hits)
|
||||
{
|
||||
results.append(QRectF(rect.x0, rect.y0, rect.x1 - rect.x0, rect.y1 - rect.y0));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
FitzDocument::FitzDocument(fz_context* context, fz_document* document) :
|
||||
m_mutex(),
|
||||
m_context(context),
|
||||
m_document(document),
|
||||
m_paperColor(Qt::white)
|
||||
{
|
||||
}
|
||||
|
||||
FitzDocument::~FitzDocument()
|
||||
{
|
||||
fz_drop_document(m_context, m_document);
|
||||
fz_drop_context(m_context);
|
||||
}
|
||||
|
||||
int FitzDocument::numberOfPages() const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
return fz_count_pages(m_context, m_document);
|
||||
}
|
||||
|
||||
Page* FitzDocument::page(int index) const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(fz_page* page = fz_load_page(m_context, m_document, index))
|
||||
{
|
||||
return new FitzPage(this, page);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FitzDocument::canBePrintedUsingCUPS() const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
return pdf_specifics(m_context, m_document) != 0;
|
||||
}
|
||||
|
||||
void FitzDocument::setPaperColor(const QColor& paperColor)
|
||||
{
|
||||
m_paperColor = paperColor;
|
||||
}
|
||||
|
||||
Outline FitzDocument::outline() const
|
||||
{
|
||||
Outline outline;
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(fz_outline* rootItem = fz_load_outline(m_context, m_document))
|
||||
{
|
||||
outline = loadOutline(rootItem);
|
||||
|
||||
fz_drop_outline(m_context, rootItem);
|
||||
}
|
||||
|
||||
return outline;
|
||||
}
|
||||
|
||||
} // Model
|
||||
|
||||
FitzPlugin::FitzPlugin(QObject* parent) : QObject(parent)
|
||||
{
|
||||
setObjectName("FitzPlugin");
|
||||
|
||||
m_locks_context.user = this;
|
||||
m_locks_context.lock = FitzPlugin::lock;
|
||||
m_locks_context.unlock = FitzPlugin::unlock;
|
||||
|
||||
m_context = fz_new_context(0, &m_locks_context, FZ_STORE_DEFAULT);
|
||||
|
||||
fz_register_document_handlers(m_context);
|
||||
}
|
||||
|
||||
FitzPlugin::~FitzPlugin()
|
||||
{
|
||||
fz_drop_context(m_context);
|
||||
}
|
||||
|
||||
Model::Document* FitzPlugin::loadDocument(const QString& filePath) const
|
||||
{
|
||||
fz_context* context = fz_clone_context(m_context);
|
||||
|
||||
if(context == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
fz_document* document = fz_open_document(context, filePath.toUtf8());
|
||||
|
||||
#else
|
||||
|
||||
fz_document* document = fz_open_document(context, QFile::encodeName(filePath));
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
if(document == 0)
|
||||
{
|
||||
fz_drop_context(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new Model::FitzDocument(context, document);
|
||||
}
|
||||
|
||||
void FitzPlugin::lock(void* user, int lock)
|
||||
{
|
||||
static_cast< FitzPlugin* >(user)->m_mutex[lock].lock();
|
||||
}
|
||||
|
||||
void FitzPlugin::unlock(void* user, int lock)
|
||||
{
|
||||
static_cast< FitzPlugin* >(user)->m_mutex[lock].unlock();
|
||||
}
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
Q_EXPORT_PLUGIN2(qpdfview_fitz, qpdfview::FitzPlugin)
|
||||
|
||||
#endif // QT_VERSION
|
136
sources/fitzmodel.h
Parasts fails
136
sources/fitzmodel.h
Parasts fails
@ -0,0 +1,136 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 S. Razi Alavizadeh
|
||||
Copyright 2014, 2018 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FITZMODEL_H
|
||||
#define FITZMODEL_H
|
||||
|
||||
#include <QMutex>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include <mupdf/fitz/context.h>
|
||||
|
||||
typedef struct fz_page_s fz_page;
|
||||
typedef struct fz_document_s fz_document;
|
||||
|
||||
}
|
||||
|
||||
#include "model.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class FitzPlugin;
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class FitzPage : public Page
|
||||
{
|
||||
friend class FitzDocument;
|
||||
|
||||
public:
|
||||
~FitzPage();
|
||||
|
||||
QSizeF size() const;
|
||||
|
||||
QImage render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const;
|
||||
|
||||
QList< Link* > links() const;
|
||||
|
||||
QString text(const QRectF& rect) const;
|
||||
|
||||
QList< QRectF > search(const QString& text, bool matchCase, bool wholeWords) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(FitzPage)
|
||||
|
||||
FitzPage(const class FitzDocument* parent, fz_page* page);
|
||||
|
||||
const class FitzDocument* m_parent;
|
||||
|
||||
fz_page* m_page;
|
||||
|
||||
};
|
||||
|
||||
class FitzDocument : public Document
|
||||
{
|
||||
friend class FitzPage;
|
||||
friend class qpdfview::FitzPlugin;
|
||||
|
||||
public:
|
||||
~FitzDocument();
|
||||
|
||||
int numberOfPages() const;
|
||||
|
||||
Page* page(int index) const;
|
||||
|
||||
bool canBePrintedUsingCUPS() const;
|
||||
|
||||
void setPaperColor(const QColor& paperColor);
|
||||
|
||||
Outline outline() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(FitzDocument)
|
||||
|
||||
FitzDocument(fz_context* context, fz_document* document);
|
||||
|
||||
mutable QMutex m_mutex;
|
||||
fz_context* m_context;
|
||||
fz_document* m_document;
|
||||
|
||||
QColor m_paperColor;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class FitzPlugin : public QObject, Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(qpdfview::Plugin)
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
Q_PLUGIN_METADATA(IID "local.qpdfview.Plugin")
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
public:
|
||||
FitzPlugin(QObject* parent = 0);
|
||||
~FitzPlugin();
|
||||
|
||||
Model::Document* loadDocument(const QString& filePath) const;
|
||||
|
||||
private:
|
||||
QMutex m_mutex[FZ_LOCK_MAX];
|
||||
fz_locks_context m_locks_context;
|
||||
fz_context* m_context;
|
||||
|
||||
static void lock(void* user, int lock);
|
||||
static void unlock(void* user, int lock);
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // FITZMODEL_H
|
76
sources/fontsdialog.cpp
Parasts fails
76
sources/fontsdialog.cpp
Parasts fails
@ -0,0 +1,76 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "fontsdialog.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHeaderView>
|
||||
#include <QStandardItemModel>
|
||||
#include <QTableView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
FontsDialog::FontsDialog(QAbstractItemModel* model, QWidget* parent) : QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("Fonts") + QLatin1String(" - qpdfview"));
|
||||
|
||||
m_tableView = new QTableView(this);
|
||||
m_tableView->setModel(model);
|
||||
|
||||
m_tableView->setAlternatingRowColors(true);
|
||||
m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
m_tableView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
m_tableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
#else
|
||||
|
||||
m_tableView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
m_tableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
m_tableView->verticalHeader()->setVisible(false);
|
||||
|
||||
m_dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, this);
|
||||
connect(m_dialogButtonBox, SIGNAL(accepted()), SLOT(accept()));
|
||||
connect(m_dialogButtonBox, SIGNAL(rejected()), SLOT(reject()));
|
||||
|
||||
setLayout(new QVBoxLayout(this));
|
||||
layout()->addWidget(m_tableView);
|
||||
layout()->addWidget(m_dialogButtonBox);
|
||||
|
||||
resize(Settings::instance()->mainWindow().fontsDialogSize(sizeHint()));
|
||||
}
|
||||
|
||||
FontsDialog::~FontsDialog()
|
||||
{
|
||||
Settings::instance()->mainWindow().setFontsDialogSize(size());
|
||||
}
|
||||
|
||||
} // qpdfview
|
53
sources/fontsdialog.h
Parasts fails
53
sources/fontsdialog.h
Parasts fails
@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FONTSDIALOG_H
|
||||
#define FONTSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QAbstractItemModel;
|
||||
class QDialogButtonBox;
|
||||
class QTableView;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class FontsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FontsDialog(QAbstractItemModel* model, QWidget* parent = 0);
|
||||
~FontsDialog();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(FontsDialog)
|
||||
|
||||
QTableView* m_tableView;
|
||||
|
||||
QDialogButtonBox* m_dialogButtonBox;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // FONTSDIALOG_H
|
336
sources/formfieldwidgets.cpp
Parasts fails
336
sources/formfieldwidgets.cpp
Parasts fails
@ -0,0 +1,336 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "formfieldwidgets.h"
|
||||
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QMutex>
|
||||
|
||||
#include <poppler-form.h>
|
||||
|
||||
#ifndef HAS_POPPLER_24
|
||||
|
||||
#define LOCK_FORM_FIELD QMutexLocker mutexLocker(m_mutex);
|
||||
|
||||
#else
|
||||
|
||||
#define LOCK_FORM_FIELD
|
||||
|
||||
#endif // HAS_POPPLER_24
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool hideOnEscape(QWidget* widget, QKeyEvent* event)
|
||||
{
|
||||
if(event->key() == Qt::Key_Escape)
|
||||
{
|
||||
widget->hide();
|
||||
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
NormalTextFieldWidget::NormalTextFieldWidget(QMutex* mutex, Poppler::FormFieldText* formField, QWidget* parent) : QLineEdit(parent),
|
||||
m_mutex(mutex),
|
||||
m_formField(formField)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
setText(m_formField->text());
|
||||
setMaxLength(m_formField->maximumLength());
|
||||
setAlignment(m_formField->textAlignment());
|
||||
setEchoMode(m_formField->isPassword() ? QLineEdit::Password : QLineEdit::Normal);
|
||||
|
||||
connect(this, SIGNAL(textChanged(QString)), SLOT(on_textChanged(QString)));
|
||||
connect(this, SIGNAL(textChanged(QString)), SIGNAL(wasModified()));
|
||||
|
||||
connect(this, SIGNAL(returnPressed()), SLOT(hide()));
|
||||
}
|
||||
|
||||
void NormalTextFieldWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(!hideOnEscape(this, event))
|
||||
{
|
||||
QLineEdit::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void NormalTextFieldWidget::on_textChanged(const QString& text)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
m_formField->setText(text);
|
||||
}
|
||||
|
||||
MultilineTextFieldWidget::MultilineTextFieldWidget(QMutex* mutex, Poppler::FormFieldText* formField, QWidget* parent) : QPlainTextEdit(parent),
|
||||
m_mutex(mutex),
|
||||
m_formField(formField)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
setPlainText(m_formField->text());
|
||||
|
||||
connect(this, SIGNAL(textChanged()), SLOT(on_textChanged()));
|
||||
connect(this, SIGNAL(textChanged()), SIGNAL(wasModified()));
|
||||
|
||||
moveCursor(QTextCursor::End);
|
||||
}
|
||||
|
||||
void MultilineTextFieldWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(!hideOnEscape(this, event))
|
||||
{
|
||||
QPlainTextEdit::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void MultilineTextFieldWidget::on_textChanged()
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
m_formField->setText(toPlainText());
|
||||
}
|
||||
|
||||
ComboBoxChoiceFieldWidget::ComboBoxChoiceFieldWidget(QMutex* mutex, Poppler::FormFieldChoice* formField, QWidget* parent) : QComboBox(parent),
|
||||
m_mutex(mutex),
|
||||
m_formField(formField)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
addItems(m_formField->choices());
|
||||
|
||||
if(!m_formField->currentChoices().isEmpty())
|
||||
{
|
||||
setCurrentIndex(m_formField->currentChoices().at(0));
|
||||
}
|
||||
|
||||
connect(this, SIGNAL(currentIndexChanged(int)), SLOT(on_currentIndexChanged(int)));
|
||||
connect(this, SIGNAL(currentIndexChanged(int)), SIGNAL(wasModified()));
|
||||
|
||||
#ifdef HAS_POPPLER_22
|
||||
|
||||
if(m_formField->isEditable())
|
||||
{
|
||||
setEditable(true);
|
||||
setInsertPolicy(QComboBox::NoInsert);
|
||||
|
||||
lineEdit()->setText(m_formField->editChoice());
|
||||
|
||||
connect(lineEdit(), SIGNAL(textChanged(QString)), SLOT(on_currentTextChanged(QString)));
|
||||
connect(lineEdit(), SIGNAL(textChanged(QString)), SIGNAL(wasModified()));
|
||||
|
||||
connect(lineEdit(), SIGNAL(returnPressed()), SLOT(hide()));
|
||||
}
|
||||
else
|
||||
{
|
||||
connect(this, SIGNAL(activated(int)), SLOT(hide()));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
connect(this, SIGNAL(activated(int)), SLOT(hide()));
|
||||
|
||||
#endif // HAS_POPPLER_22
|
||||
}
|
||||
|
||||
void ComboBoxChoiceFieldWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(!hideOnEscape(this, event))
|
||||
{
|
||||
QComboBox::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBoxChoiceFieldWidget::showPopup()
|
||||
{
|
||||
QComboBox::showPopup();
|
||||
|
||||
graphicsProxyWidget()->setZValue(1.0);
|
||||
}
|
||||
|
||||
void ComboBoxChoiceFieldWidget::hidePopup()
|
||||
{
|
||||
QComboBox::hidePopup();
|
||||
|
||||
graphicsProxyWidget()->setZValue(0.0);
|
||||
}
|
||||
|
||||
void ComboBoxChoiceFieldWidget::on_currentIndexChanged(int index)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
m_formField->setCurrentChoices(QList< int >() << index);
|
||||
}
|
||||
|
||||
void ComboBoxChoiceFieldWidget::on_currentTextChanged(const QString& text)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
#ifdef HAS_POPPLER_22
|
||||
|
||||
m_formField->setEditChoice(text);
|
||||
|
||||
#endif // HAS_POPPLER_22
|
||||
}
|
||||
|
||||
ListBoxChoiceFieldWidget::ListBoxChoiceFieldWidget(QMutex* mutex, Poppler::FormFieldChoice* formField, QWidget* parent) : QListWidget(parent),
|
||||
m_mutex(mutex),
|
||||
m_formField(formField)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
addItems(m_formField->choices());
|
||||
setSelectionMode(m_formField->multiSelect() ? QAbstractItemView::MultiSelection : QAbstractItemView::SingleSelection);
|
||||
|
||||
foreach(int index, m_formField->currentChoices())
|
||||
{
|
||||
if(index >= 0 && index < count())
|
||||
{
|
||||
item(index)->setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
connect(this, SIGNAL(itemSelectionChanged()), SLOT(on_itemSelectionChanged()));
|
||||
connect(this, SIGNAL(itemSelectionChanged()), SIGNAL(wasModified()));
|
||||
}
|
||||
|
||||
void ListBoxChoiceFieldWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(!hideOnEscape(this, event))
|
||||
{
|
||||
QListWidget::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void ListBoxChoiceFieldWidget::on_itemSelectionChanged()
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
QList< int > currentChoices;
|
||||
|
||||
for(int index = 0; index < count(); ++index)
|
||||
{
|
||||
if(item(index)->isSelected())
|
||||
{
|
||||
currentChoices.append(index);
|
||||
}
|
||||
}
|
||||
|
||||
m_formField->setCurrentChoices(currentChoices);
|
||||
}
|
||||
|
||||
CheckBoxChoiceFieldWidget::CheckBoxChoiceFieldWidget(QMutex* mutex, Poppler::FormFieldButton* formField, QWidget* parent) : QCheckBox(parent),
|
||||
m_mutex(mutex),
|
||||
m_formField(formField)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
setChecked(m_formField->state());
|
||||
|
||||
connect(this, SIGNAL(toggled(bool)), SLOT(on_toggled(bool)));
|
||||
connect(this, SIGNAL(toggled(bool)), SIGNAL(wasModified()));
|
||||
}
|
||||
|
||||
void CheckBoxChoiceFieldWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(!hideOnEscape(this, event))
|
||||
{
|
||||
QCheckBox::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void CheckBoxChoiceFieldWidget::on_toggled(bool checked)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
m_formField->setState(checked);
|
||||
}
|
||||
|
||||
RadioChoiceFieldWidget::Siblings RadioChoiceFieldWidget::s_siblings;
|
||||
|
||||
RadioChoiceFieldWidget::RadioChoiceFieldWidget(QMutex* mutex, Poppler::FormFieldButton* formField, QWidget* parent) : QRadioButton(parent),
|
||||
m_mutex(mutex),
|
||||
m_formField(formField)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
s_siblings.insert(qMakePair(m_mutex, m_formField->id()), this);
|
||||
|
||||
setAutoExclusive(false);
|
||||
setChecked(m_formField->state());
|
||||
|
||||
connect(this, SIGNAL(toggled(bool)), SLOT(on_toggled(bool)));
|
||||
connect(this, SIGNAL(toggled(bool)), SIGNAL(wasModified()));
|
||||
}
|
||||
|
||||
RadioChoiceFieldWidget::~RadioChoiceFieldWidget()
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
s_siblings.remove(qMakePair(m_mutex, m_formField->id()));
|
||||
}
|
||||
|
||||
void RadioChoiceFieldWidget::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(!hideOnEscape(this, event))
|
||||
{
|
||||
QRadioButton::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void RadioChoiceFieldWidget::on_toggled(bool checked)
|
||||
{
|
||||
LOCK_FORM_FIELD
|
||||
|
||||
m_formField->setState(checked);
|
||||
|
||||
if(checked)
|
||||
{
|
||||
const QList< int > siblings = m_formField->siblings();
|
||||
|
||||
#ifndef HAS_POPPLER_24
|
||||
|
||||
mutexLocker.unlock();
|
||||
|
||||
#endif // HAS_POPPLER_24
|
||||
|
||||
foreach(int id, siblings)
|
||||
{
|
||||
const QPair< QMutex*, int > key = qMakePair(m_mutex, id);
|
||||
|
||||
if(s_siblings.contains(key))
|
||||
{
|
||||
s_siblings.value(key)->setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // qpdfview
|
201
sources/formfieldwidgets.h
Parasts fails
201
sources/formfieldwidgets.h
Parasts fails
@ -0,0 +1,201 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FORMFIELDWIDGETS_H
|
||||
#define FORMFIELDWIDGETS_H
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QRadioButton>
|
||||
|
||||
class QMutex;
|
||||
|
||||
namespace Poppler
|
||||
{
|
||||
class FormField;
|
||||
class FormFieldText;
|
||||
class FormFieldChoice;
|
||||
class FormFieldButton;
|
||||
}
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class NormalTextFieldWidget : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NormalTextFieldWidget(QMutex* mutex, Poppler::FormFieldText* formField, QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
protected slots:
|
||||
void on_textChanged(const QString& text);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(NormalTextFieldWidget)
|
||||
|
||||
QMutex* m_mutex;
|
||||
Poppler::FormFieldText* m_formField;
|
||||
|
||||
};
|
||||
|
||||
class MultilineTextFieldWidget : public QPlainTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MultilineTextFieldWidget(QMutex* mutex, Poppler::FormFieldText* formField, QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
protected slots:
|
||||
void on_textChanged();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(MultilineTextFieldWidget)
|
||||
|
||||
QMutex* m_mutex;
|
||||
Poppler::FormFieldText* m_formField;
|
||||
|
||||
};
|
||||
|
||||
class ComboBoxChoiceFieldWidget : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ComboBoxChoiceFieldWidget(QMutex* mutex, Poppler::FormFieldChoice* formField, QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
void showPopup();
|
||||
void hidePopup();
|
||||
|
||||
protected slots:
|
||||
void on_currentIndexChanged(int index);
|
||||
void on_currentTextChanged(const QString& text);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ComboBoxChoiceFieldWidget)
|
||||
|
||||
QMutex* m_mutex;
|
||||
Poppler::FormFieldChoice* m_formField;
|
||||
|
||||
};
|
||||
|
||||
class ListBoxChoiceFieldWidget : public QListWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ListBoxChoiceFieldWidget(QMutex* mutex, Poppler::FormFieldChoice* formField, QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
protected slots:
|
||||
void on_itemSelectionChanged();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ListBoxChoiceFieldWidget)
|
||||
|
||||
QMutex* m_mutex;
|
||||
Poppler::FormFieldChoice* m_formField;
|
||||
|
||||
};
|
||||
|
||||
class CheckBoxChoiceFieldWidget : public QCheckBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckBoxChoiceFieldWidget(QMutex* mutex, Poppler::FormFieldButton* formField, QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
protected slots:
|
||||
void on_toggled(bool checked);
|
||||
|
||||
protected slots:
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(CheckBoxChoiceFieldWidget)
|
||||
|
||||
QMutex* m_mutex;
|
||||
Poppler::FormFieldButton* m_formField;
|
||||
|
||||
};
|
||||
|
||||
class RadioChoiceFieldWidget : public QRadioButton
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RadioChoiceFieldWidget(QMutex* mutex, Poppler::FormFieldButton* formField, QWidget* parent = 0);
|
||||
~RadioChoiceFieldWidget();
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
protected slots:
|
||||
void on_toggled(bool checked);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(RadioChoiceFieldWidget)
|
||||
|
||||
typedef QMap< QPair< QMutex*, int >, RadioChoiceFieldWidget* > Siblings;
|
||||
static Siblings s_siblings;
|
||||
|
||||
QMutex* m_mutex;
|
||||
Poppler::FormFieldButton* m_formField;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // FORMFIELDWIDGETS_H
|
77
sources/global.h
Parasts fails
77
sources/global.h
Parasts fails
@ -0,0 +1,77 @@
|
||||
/*
|
||||
|
||||
Copyright 2013, 2015 Adam Reichold
|
||||
Copyright 2013 Alexander Volkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef GLOBAL_H
|
||||
#define GLOBAL_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <qnumeric.h>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
enum Rotation
|
||||
{
|
||||
RotateBy0 = 0,
|
||||
RotateBy90 = 1,
|
||||
RotateBy180 = 2,
|
||||
RotateBy270 = 3,
|
||||
NumberOfRotations = 4
|
||||
};
|
||||
|
||||
enum RubberBandMode
|
||||
{
|
||||
ModifiersMode = 0,
|
||||
CopyToClipboardMode = 1,
|
||||
AddAnnotationMode = 2,
|
||||
ZoomToSelectionMode = 3,
|
||||
NumberOfRubberBandModes = 4
|
||||
};
|
||||
|
||||
enum LayoutMode
|
||||
{
|
||||
SinglePageMode = 0,
|
||||
TwoPagesMode = 1,
|
||||
TwoPagesWithCoverPageMode = 2,
|
||||
MultiplePagesMode = 3,
|
||||
NumberOfLayoutModes = 4
|
||||
};
|
||||
|
||||
enum ScaleMode
|
||||
{
|
||||
ScaleFactorMode = 0,
|
||||
FitToPageWidthMode = 1,
|
||||
FitToPageSizeMode = 2,
|
||||
NumberOfScaleModes = 3
|
||||
};
|
||||
|
||||
enum CompositionMode
|
||||
{
|
||||
DefaultCompositionMode = 0,
|
||||
DarkenWithPaperColorMode = 1,
|
||||
LightenWithPaperColorMode = 2,
|
||||
NumberOfCompositionModes = 3
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // GLOBAL_H
|
132
sources/helpdialog.cpp
Parasts fails
132
sources/helpdialog.cpp
Parasts fails
@ -0,0 +1,132 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 Marshall Banana
|
||||
Copyright 2013 Benjamin Eltzner
|
||||
Copyright 2013, 2018 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "helpdialog.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDir>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QTextBrowser>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
HelpDialog::HelpDialog(QWidget* parent) : QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("Help") + QLatin1String(" - qpdfview"));
|
||||
|
||||
m_textBrowser = new QTextBrowser(this);
|
||||
m_textBrowser->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard);
|
||||
m_textBrowser->setSearchPaths(QStringList() << QDir(QApplication::applicationDirPath()).filePath("data") << DATA_INSTALL_PATH << ":/");
|
||||
|
||||
//: Please replace by file name of localized help if available, e.g. "help_fr.html".
|
||||
m_textBrowser->setSource(QUrl::fromLocalFile(tr("help.html")));
|
||||
|
||||
if(m_textBrowser->document()->isEmpty())
|
||||
{
|
||||
m_textBrowser->setSource(QUrl::fromLocalFile("help.html"));
|
||||
}
|
||||
|
||||
m_dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, this);
|
||||
connect(m_dialogButtonBox, SIGNAL(accepted()), SLOT(accept()));
|
||||
connect(m_dialogButtonBox, SIGNAL(rejected()), SLOT(reject()));
|
||||
|
||||
m_searchLineEdit = new QLineEdit(this);
|
||||
connect(m_searchLineEdit, SIGNAL(returnPressed()), SLOT(on_findNext_triggered()));
|
||||
connect(m_searchLineEdit, SIGNAL(textEdited(QString)), SLOT(on_search_textEdited()));
|
||||
|
||||
m_findPreviousButton = m_dialogButtonBox->addButton(tr("Find previous"), QDialogButtonBox::ActionRole);
|
||||
m_findPreviousButton->setShortcut(QKeySequence::FindPrevious);
|
||||
connect(m_findPreviousButton, SIGNAL(clicked()), SLOT(on_findPrevious_triggered()));
|
||||
|
||||
m_findNextButton = m_dialogButtonBox->addButton(tr("Find next"), QDialogButtonBox::ActionRole);
|
||||
m_findNextButton->setShortcut(QKeySequence::FindNext);
|
||||
connect(m_findNextButton, SIGNAL(clicked()), SLOT(on_findNext_triggered()));
|
||||
|
||||
// Default buttons would interfere with search funtionality...
|
||||
foreach(QAbstractButton* abstractButton, m_dialogButtonBox->buttons())
|
||||
{
|
||||
QPushButton* pushButton = qobject_cast< QPushButton* >(abstractButton);
|
||||
|
||||
if(pushButton != 0)
|
||||
{
|
||||
pushButton->setAutoDefault(false);
|
||||
pushButton->setDefault(false);
|
||||
}
|
||||
}
|
||||
|
||||
setLayout(new QVBoxLayout(this));
|
||||
layout()->addWidget(m_textBrowser);
|
||||
layout()->addWidget(m_searchLineEdit);
|
||||
layout()->addWidget(m_dialogButtonBox);
|
||||
|
||||
resize(Settings::instance()->mainWindow().contentsDialogSize(sizeHint()));
|
||||
|
||||
m_searchLineEdit->setFocus();
|
||||
}
|
||||
|
||||
HelpDialog::~HelpDialog()
|
||||
{
|
||||
Settings::instance()->mainWindow().setContentsDialogSize(size());
|
||||
}
|
||||
|
||||
void HelpDialog::on_findPrevious_triggered()
|
||||
{
|
||||
if(!m_searchLineEdit->text().isEmpty() && m_textBrowser->find(m_searchLineEdit->text(), QTextDocument::FindBackward))
|
||||
{
|
||||
m_textBrowser->setFocus();
|
||||
|
||||
m_searchLineEdit->setStyleSheet(QLatin1String("background-color: #80ff80"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_searchLineEdit->setStyleSheet(QLatin1String("background-color: #ff8080"));
|
||||
}
|
||||
}
|
||||
|
||||
void HelpDialog::on_findNext_triggered()
|
||||
{
|
||||
if(!m_searchLineEdit->text().isEmpty() && m_textBrowser->find(m_searchLineEdit->text()))
|
||||
{
|
||||
m_textBrowser->setFocus();
|
||||
|
||||
m_searchLineEdit->setStyleSheet(QLatin1String("background-color: #80ff80"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_searchLineEdit->setStyleSheet(QLatin1String("background-color: #ff8080"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void HelpDialog::on_search_textEdited()
|
||||
{
|
||||
m_searchLineEdit->setStyleSheet(QString());
|
||||
}
|
||||
|
||||
} // qpdfview
|
63
sources/helpdialog.h
Parasts fails
63
sources/helpdialog.h
Parasts fails
@ -0,0 +1,63 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Benjamin Eltzner
|
||||
Copyright 2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HELPDIALOG_H
|
||||
#define HELPDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QDialogButtonBox;
|
||||
class QTextBrowser;
|
||||
class QLineEdit;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class HelpDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HelpDialog(QWidget* parent = 0);
|
||||
~HelpDialog();
|
||||
|
||||
protected slots:
|
||||
void on_findPrevious_triggered();
|
||||
void on_findNext_triggered();
|
||||
void on_search_textEdited();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(HelpDialog)
|
||||
|
||||
QTextBrowser* m_textBrowser;
|
||||
|
||||
QDialogButtonBox* m_dialogButtonBox;
|
||||
|
||||
QLineEdit* m_searchLineEdit;
|
||||
QPushButton* m_findPreviousButton;
|
||||
QPushButton* m_findNextButton;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // HELPDIALOG_H
|
209
sources/imagemodel.cpp
Parasts fails
209
sources/imagemodel.cpp
Parasts fails
@ -0,0 +1,209 @@
|
||||
/*
|
||||
|
||||
Copyright 2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "imagemodel.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QImageWriter>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace qpdfview;
|
||||
using namespace qpdfview::Model;
|
||||
|
||||
inline qreal dotsPerInchX(const QImage& image)
|
||||
{
|
||||
return 0.0254 * image.dotsPerMeterX();
|
||||
}
|
||||
|
||||
inline qreal dotsPerInchY(const QImage& image)
|
||||
{
|
||||
return 0.0254 * image.dotsPerMeterY();
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
|
||||
ImagePage::ImagePage(const QImage& image) :
|
||||
m_image(image)
|
||||
{
|
||||
}
|
||||
|
||||
QSizeF ImagePage::size() const
|
||||
{
|
||||
return QSizeF(m_image.width() * 72.0 / dotsPerInchX(m_image),
|
||||
m_image.height() * 72.0 / dotsPerInchY(m_image));
|
||||
}
|
||||
|
||||
QImage ImagePage::render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const
|
||||
{
|
||||
QTransform transform;
|
||||
|
||||
transform.scale(horizontalResolution / dotsPerInchX(m_image),
|
||||
verticalResolution / dotsPerInchY(m_image));
|
||||
|
||||
switch(rotation)
|
||||
{
|
||||
default:
|
||||
case RotateBy0:
|
||||
break;
|
||||
case RotateBy90:
|
||||
transform.rotate(90.0);
|
||||
break;
|
||||
case RotateBy180:
|
||||
transform.rotate(180.0);
|
||||
break;
|
||||
case RotateBy270:
|
||||
transform.rotate(270.0);
|
||||
break;
|
||||
}
|
||||
|
||||
QImage image = m_image.transformed(transform, Qt::SmoothTransformation);
|
||||
|
||||
if(!boundingRect.isNull())
|
||||
{
|
||||
image = image.copy(boundingRect);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
ImageDocument::ImageDocument(const QImage& image) :
|
||||
m_image(image)
|
||||
{
|
||||
}
|
||||
|
||||
int ImageDocument::numberOfPages() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
Page* ImageDocument::page(int index) const
|
||||
{
|
||||
return index == 0 ? new ImagePage(m_image) : 0;
|
||||
}
|
||||
|
||||
QStringList ImageDocument::saveFilter() const
|
||||
{
|
||||
QStringList formats;
|
||||
|
||||
foreach(const QByteArray& format, QImageWriter::supportedImageFormats())
|
||||
{
|
||||
const QString name = QString::fromLocal8Bit(format);
|
||||
|
||||
formats.append(QLatin1String("*.") + name);
|
||||
}
|
||||
|
||||
return QStringList() << tr("Image (%1)").arg(formats.join(QLatin1String(" ")));
|
||||
}
|
||||
|
||||
bool ImageDocument::canSave() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImageDocument::save(const QString& filePath, bool withChanges) const
|
||||
{
|
||||
Q_UNUSED(withChanges);
|
||||
|
||||
QImageWriter writer(filePath);
|
||||
|
||||
if(!writer.write(m_image))
|
||||
{
|
||||
qWarning() << writer.errorString();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Properties ImageDocument::properties() const
|
||||
{
|
||||
Properties properties;
|
||||
|
||||
properties.push_back(qMakePair(tr("Size"), QString("%1 px x %2 px").arg(m_image.width()).arg(m_image.height())));
|
||||
properties.push_back(qMakePair(tr("Resolution"), QString("%1 dpi x %2 dpi").arg(dotsPerInchX(m_image), 0, 'f', 1).arg(dotsPerInchY(m_image), 0, 'f', 1)));
|
||||
properties.push_back(qMakePair(tr("Depth"), QString("%1 bits").arg(m_image.depth())));
|
||||
|
||||
switch(m_image.format())
|
||||
{
|
||||
default:
|
||||
break;
|
||||
case QImage::Format_Mono:
|
||||
case QImage::Format_MonoLSB:
|
||||
properties.push_back(qMakePair(tr("Format"), tr("Monochrome")));
|
||||
break;
|
||||
case QImage::Format_Indexed8:
|
||||
properties.push_back(qMakePair(tr("Format"), tr("Indexed")));
|
||||
break;
|
||||
case QImage::Format_RGB32:
|
||||
properties.push_back(qMakePair(tr("Format"), tr("32 bits RGB")));
|
||||
break;
|
||||
case QImage::Format_ARGB32:
|
||||
properties.push_back(qMakePair(tr("Format"), tr("32 bits ARGB")));
|
||||
break;
|
||||
case QImage::Format_RGB16:
|
||||
case QImage::Format_RGB555:
|
||||
case QImage::Format_RGB444:
|
||||
properties.push_back(qMakePair(tr("Format"), tr("16 bits RGB")));
|
||||
break;
|
||||
case QImage::Format_RGB666:
|
||||
case QImage::Format_RGB888:
|
||||
properties.push_back(qMakePair(tr("Format"), tr("24 bits RGB")));
|
||||
break;
|
||||
}
|
||||
|
||||
foreach(const QString& key, m_image.textKeys())
|
||||
{
|
||||
properties.push_back(qMakePair(key, m_image.text(key)));
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
} // Model
|
||||
|
||||
ImagePlugin::ImagePlugin(QObject* parent) : QObject(parent)
|
||||
{
|
||||
setObjectName("ImagePlugin");
|
||||
}
|
||||
|
||||
Model::Document* ImagePlugin::loadDocument(const QString& filePath) const
|
||||
{
|
||||
QImage image(filePath);
|
||||
|
||||
return !image.isNull() ? new Model::ImageDocument(image) : 0;
|
||||
}
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
Q_EXPORT_PLUGIN2(qpdfview_image, qpdfview::ImagePlugin)
|
||||
|
||||
#endif // QT_VERSION
|
105
sources/imagemodel.h
Parasts fails
105
sources/imagemodel.h
Parasts fails
@ -0,0 +1,105 @@
|
||||
/*
|
||||
|
||||
Copyright 2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef IMAGEMODEL_H
|
||||
#define IMAGEMODEL_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "model.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class ImagePlugin;
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class ImagePage : public Page
|
||||
{
|
||||
friend class ImageDocument;
|
||||
|
||||
public:
|
||||
QSizeF size() const;
|
||||
|
||||
QImage render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ImagePage)
|
||||
|
||||
ImagePage(const QImage& image);
|
||||
|
||||
QImage m_image;
|
||||
|
||||
};
|
||||
|
||||
class ImageDocument : public Document
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Model::ImageDocument)
|
||||
|
||||
friend class qpdfview::ImagePlugin;
|
||||
|
||||
public:
|
||||
int numberOfPages() const;
|
||||
|
||||
Page* page(int index) const;
|
||||
|
||||
QStringList saveFilter() const;
|
||||
|
||||
bool canSave() const;
|
||||
bool save(const QString& filePath, bool withChanges) const;
|
||||
|
||||
Properties properties() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ImageDocument)
|
||||
|
||||
ImageDocument(const QImage& image);
|
||||
|
||||
QImage m_image;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class ImagePlugin : public QObject, Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(qpdfview::Plugin)
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
Q_PLUGIN_METADATA(IID "local.qpdfview.Plugin")
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
public:
|
||||
ImagePlugin(QObject* parent = 0);
|
||||
|
||||
Model::Document* loadDocument(const QString& filePath) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ImagePlugin)
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // IMAGEMODEL_H
|
509
sources/main.cpp
Parasts fails
509
sources/main.cpp
Parasts fails
@ -0,0 +1,509 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 Marshall Banana
|
||||
Copyright 2012-2013, 2018 Adam Reichold
|
||||
Copyright 2014 Dorian Scholz
|
||||
Copyright 2012 Michał Trybus
|
||||
Copyright 2013 Chris Young
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QInputDialog>
|
||||
#include <QLibraryInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QScopedPointer>
|
||||
#include <QTranslator>
|
||||
|
||||
#ifdef WITH_DBUS
|
||||
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
|
||||
#endif // WITH_DBUS
|
||||
|
||||
#ifdef WITH_SYNCTEX
|
||||
|
||||
#include <synctex_parser.h>
|
||||
|
||||
#ifndef HAS_SYNCTEX_2
|
||||
|
||||
typedef synctex_scanner_t synctex_scanner_p;
|
||||
typedef synctex_node_t synctex_node_p;
|
||||
|
||||
#define synctex_scanner_next_result(scanner) synctex_next_result(scanner)
|
||||
#define synctex_display_query(scanner, file, line, column, page) synctex_display_query(scanner, file, line, column)
|
||||
|
||||
#endif // HAS_SYNCTEX_2
|
||||
|
||||
#endif // WITH_SYNCTEX
|
||||
|
||||
#include "documentview.h"
|
||||
#include "database.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#ifdef WITH_SIGNALS
|
||||
|
||||
#include "signalhandler.h"
|
||||
|
||||
#endif // WITH_SIGNALS
|
||||
|
||||
#ifdef __amigaos4__
|
||||
|
||||
#include <proto/dos.h>
|
||||
#include <workbench/startup.h>
|
||||
|
||||
const char* __attribute__((used)) stack_cookie = "\0$STACK:500000\0";
|
||||
|
||||
#endif // __amigaos4__
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace qpdfview;
|
||||
|
||||
struct File
|
||||
{
|
||||
QString filePath;
|
||||
int page;
|
||||
|
||||
QString sourceName;
|
||||
int sourceLine;
|
||||
int sourceColumn;
|
||||
QRectF enclosingBox;
|
||||
|
||||
File() : filePath(), page(-1), sourceName(), sourceLine(-1), sourceColumn(-1), enclosingBox() {}
|
||||
|
||||
};
|
||||
|
||||
enum ExitStatus
|
||||
{
|
||||
ExitOk = 0,
|
||||
ExitUnknownArgument = 1,
|
||||
ExitIllegalArgument = 2,
|
||||
ExitInconsistentArguments = 3,
|
||||
ExitDBusError = 4
|
||||
};
|
||||
|
||||
bool unique = false;
|
||||
bool quiet = false;
|
||||
|
||||
QString instanceName;
|
||||
QString searchText;
|
||||
|
||||
QList< File > files;
|
||||
|
||||
MainWindow* mainWindow = 0;
|
||||
|
||||
bool loadTranslator(QTranslator* const translator, const QString& fileName, const QString& path)
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(4,8,0)
|
||||
|
||||
const bool ok = translator->load(QLocale::system(), fileName, "_", path);
|
||||
|
||||
#else
|
||||
|
||||
const bool ok = translator->load(fileName + "_" + QLocale::system().name(), path);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
if(ok)
|
||||
{
|
||||
qApp->installTranslator(translator);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void loadTranslators()
|
||||
{
|
||||
QTranslator* toolkitTranslator = new QTranslator(qApp);
|
||||
loadTranslator(toolkitTranslator, "qt", QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||
|
||||
QTranslator* applicationTranslator = new QTranslator(qApp);
|
||||
if(loadTranslator(applicationTranslator, "qpdfview", QDir(QApplication::applicationDirPath()).filePath("data"))) {}
|
||||
else if(loadTranslator(applicationTranslator, "qpdfview", DATA_INSTALL_PATH)) {}
|
||||
else if(loadTranslator(applicationTranslator, "qpdfview", ":/")) {}
|
||||
}
|
||||
|
||||
void parseCommandLineArguments()
|
||||
{
|
||||
bool instanceNameIsNext = false;
|
||||
bool searchTextIsNext = false;
|
||||
bool noMoreOptions = false;
|
||||
|
||||
QRegExp fileAndPageRegExp("(.+)#(\\d+)");
|
||||
QRegExp fileAndSourceRegExp("(.+)#src:(.+):(\\d+):(\\d+)");
|
||||
QRegExp instanceNameRegExp("[A-Za-z_]+[A-Za-z0-9_]*");
|
||||
|
||||
QStringList arguments = QApplication::arguments();
|
||||
|
||||
if(!arguments.isEmpty())
|
||||
{
|
||||
arguments.removeFirst();
|
||||
}
|
||||
|
||||
foreach(const QString& argument, arguments)
|
||||
{
|
||||
if(instanceNameIsNext)
|
||||
{
|
||||
if(argument.isEmpty())
|
||||
{
|
||||
qCritical() << QObject::tr("An empty instance name is not allowed.");
|
||||
exit(ExitIllegalArgument);
|
||||
}
|
||||
|
||||
instanceNameIsNext = false;
|
||||
instanceName = argument;
|
||||
}
|
||||
else if(searchTextIsNext)
|
||||
{
|
||||
if(argument.isEmpty())
|
||||
{
|
||||
qCritical() << QObject::tr("An empty search text is not allowed.");
|
||||
exit(ExitIllegalArgument);
|
||||
}
|
||||
|
||||
searchTextIsNext = false;
|
||||
searchText = argument;
|
||||
}
|
||||
else if(!noMoreOptions && argument.startsWith("--"))
|
||||
{
|
||||
if(argument == QLatin1String("--unique"))
|
||||
{
|
||||
unique = true;
|
||||
}
|
||||
else if(argument == QLatin1String("--quiet"))
|
||||
{
|
||||
quiet = true;
|
||||
}
|
||||
else if(argument == QLatin1String("--instance"))
|
||||
{
|
||||
instanceNameIsNext = true;
|
||||
}
|
||||
else if(argument == QLatin1String("--search"))
|
||||
{
|
||||
searchTextIsNext = true;
|
||||
}
|
||||
else if(argument == QLatin1String("--choose-instance"))
|
||||
{
|
||||
bool ok = false;
|
||||
const QString chosenInstanceName = QInputDialog::getItem(0, MainWindow::tr("Choose instance"), MainWindow::tr("Instance:"), Database::instance()->knownInstanceNames(), 0, true, &ok);
|
||||
|
||||
if(ok)
|
||||
{
|
||||
instanceName = chosenInstanceName;
|
||||
}
|
||||
}
|
||||
else if(argument == QLatin1String("--help"))
|
||||
{
|
||||
std::cout << "Usage: qpdfview [options] [--] [file[#page]] [file[#src:name:line:column]] ..." << std::endl
|
||||
<< std::endl
|
||||
<< "Available options:" << std::endl
|
||||
<< " --help Show this information" << std::endl
|
||||
<< " --quiet Suppress warning messages when opening files" << std::endl
|
||||
<< " --search text Search for text in the current tab" << std::endl
|
||||
<< " --unique Open files as tabs in unique window" << std::endl
|
||||
<< " --unique --instance name Open files as tabs in named instance" << std::endl
|
||||
<< " --unique --choose-instance Open files as tabs after choosing an instance name" << std::endl
|
||||
<< std::endl
|
||||
<< "Please report bugs at \"https://launchpad.net/qpdfview\"." << std::endl;
|
||||
|
||||
exit(ExitOk);
|
||||
}
|
||||
else if(argument == QLatin1String("--"))
|
||||
{
|
||||
noMoreOptions = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << QObject::tr("Unknown command-line option '%1'.").arg(argument);
|
||||
exit(ExitUnknownArgument);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
File file;
|
||||
|
||||
if(fileAndPageRegExp.exactMatch(argument))
|
||||
{
|
||||
file.filePath = fileAndPageRegExp.cap(1);
|
||||
file.page = fileAndPageRegExp.cap(2).toInt();
|
||||
}
|
||||
else if(fileAndSourceRegExp.exactMatch(argument))
|
||||
{
|
||||
file.filePath = fileAndSourceRegExp.cap(1);
|
||||
file.sourceName = fileAndSourceRegExp.cap(2);
|
||||
file.sourceLine = fileAndSourceRegExp.cap(3).toInt();
|
||||
file.sourceColumn = fileAndSourceRegExp.cap(4).toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
file.filePath = argument;
|
||||
}
|
||||
|
||||
files.append(file);
|
||||
}
|
||||
}
|
||||
|
||||
if(instanceNameIsNext)
|
||||
{
|
||||
qCritical() << QObject::tr("Using '--instance' requires an instance name.");
|
||||
exit(ExitInconsistentArguments);
|
||||
}
|
||||
|
||||
if(!unique && !instanceName.isEmpty())
|
||||
{
|
||||
qCritical() << QObject::tr("Using '--instance' is not allowed without using '--unique'.");
|
||||
exit(ExitInconsistentArguments);
|
||||
}
|
||||
|
||||
if(!instanceName.isEmpty() && !instanceNameRegExp.exactMatch(instanceName))
|
||||
{
|
||||
qCritical() << QObject::tr("An instance name must only contain the characters \"[A-Z][a-z][0-9]_\" and must not begin with a digit.");
|
||||
exit(ExitIllegalArgument);
|
||||
}
|
||||
|
||||
if(searchTextIsNext)
|
||||
{
|
||||
qCritical() << QObject::tr("Using '--search' requires a search text.");
|
||||
exit(ExitInconsistentArguments);
|
||||
}
|
||||
}
|
||||
|
||||
void parseWorkbenchExtendedSelection(int argc, char** argv)
|
||||
{
|
||||
#ifdef __amigaos4__
|
||||
|
||||
if(argc == 0)
|
||||
{
|
||||
const int pathLength = 1024;
|
||||
const QScopedArrayPointer< char > filePath(new char[pathLength]);
|
||||
|
||||
const struct WBStartup* wbStartup = reinterpret_cast< struct WBStartup* >(argv);
|
||||
|
||||
for(int index = 1; index < wbStartup->sm_NumArgs; ++index)
|
||||
{
|
||||
const struct WBArg* wbArg = wbStartup->sm_ArgList + index;
|
||||
|
||||
if((wbArg->wa_Lock) && (*wbArg->wa_Name))
|
||||
{
|
||||
IDOS->DevNameFromLock(wbArg->wa_Lock, filePath.data(), pathLength, DN_FULLPATH);
|
||||
IDOS->AddPart(filePath.data(), wbArg->wa_Name, pathLength);
|
||||
|
||||
File file;
|
||||
file.filePath = filePath.data();
|
||||
|
||||
files.append(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Q_UNUSED(argc);
|
||||
Q_UNUSED(argv);
|
||||
|
||||
#endif // __amigaos4__
|
||||
}
|
||||
|
||||
void resolveSourceReferences()
|
||||
{
|
||||
#ifdef WITH_SYNCTEX
|
||||
|
||||
for(int index = 0; index < files.count(); ++index)
|
||||
{
|
||||
File& file = files[index];
|
||||
|
||||
if(!file.sourceName.isNull())
|
||||
{
|
||||
if(synctex_scanner_p scanner = synctex_scanner_new_with_output_file(file.filePath.toLocal8Bit(), 0, 1))
|
||||
{
|
||||
if(synctex_display_query(scanner, file.sourceName.toLocal8Bit(), file.sourceLine, file.sourceColumn, -1) > 0)
|
||||
{
|
||||
for(synctex_node_p node = synctex_scanner_next_result(scanner); node != 0; node = synctex_scanner_next_result(scanner))
|
||||
{
|
||||
int page = synctex_node_page(node);
|
||||
QRectF enclosingBox(synctex_node_box_visible_h(node), synctex_node_box_visible_v(node), synctex_node_box_visible_width(node), synctex_node_box_visible_height(node));
|
||||
|
||||
if(file.page != page)
|
||||
{
|
||||
file.page = page;
|
||||
file.enclosingBox = enclosingBox;
|
||||
}
|
||||
else
|
||||
{
|
||||
file.enclosingBox = file.enclosingBox.united(enclosingBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synctex_scanner_free(scanner);
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << DocumentView::tr("SyncTeX data for '%1' could not be found.").arg(file.filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // WITH_SYNCTEX
|
||||
}
|
||||
|
||||
void activateUniqueInstance()
|
||||
{
|
||||
qApp->setObjectName(instanceName);
|
||||
|
||||
#ifdef WITH_DBUS
|
||||
|
||||
if(unique)
|
||||
{
|
||||
QScopedPointer< QDBusInterface > interface(MainWindowAdaptor::createInterface());
|
||||
|
||||
if(interface->isValid())
|
||||
{
|
||||
interface->call("raiseAndActivate");
|
||||
|
||||
foreach(const File& file, files)
|
||||
{
|
||||
QDBusReply< bool > reply = interface->call("jumpToPageOrOpenInNewTab", QFileInfo(file.filePath).absoluteFilePath(), file.page, true, file.enclosingBox, quiet);
|
||||
|
||||
if(!reply.isValid())
|
||||
{
|
||||
qCritical() << QDBusConnection::sessionBus().lastError().message();
|
||||
|
||||
exit(ExitDBusError);
|
||||
}
|
||||
}
|
||||
|
||||
if(!files.isEmpty())
|
||||
{
|
||||
interface->call("saveDatabase");
|
||||
}
|
||||
|
||||
if(!searchText.isEmpty())
|
||||
{
|
||||
interface->call("startSearch", searchText);
|
||||
}
|
||||
|
||||
exit(ExitOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
mainWindow = new MainWindow();
|
||||
|
||||
if(MainWindowAdaptor::createAdaptor(mainWindow) == 0)
|
||||
{
|
||||
qCritical() << QDBusConnection::sessionBus().lastError().message();
|
||||
|
||||
delete mainWindow;
|
||||
exit(ExitDBusError);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mainWindow = new MainWindow();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
mainWindow = new MainWindow();
|
||||
|
||||
#endif // WITH_DBUS
|
||||
}
|
||||
|
||||
void prepareSignalHandler()
|
||||
{
|
||||
#ifdef WITH_SIGNALS
|
||||
|
||||
if(SignalHandler::prepareSignals())
|
||||
{
|
||||
SignalHandler* signalHandler = new SignalHandler(mainWindow);
|
||||
|
||||
QObject::connect(signalHandler, SIGNAL(sigIntReceived()), mainWindow, SLOT(close()));
|
||||
QObject::connect(signalHandler, SIGNAL(sigTermReceived()), mainWindow, SLOT(close()));
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << QObject::tr("Could not prepare signal handler.");
|
||||
}
|
||||
|
||||
#endif // WITH_SIGNALS
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
qRegisterMetaType< QList< QRectF > >("QList<QRectF>");
|
||||
qRegisterMetaType< Rotation >("Rotation");
|
||||
qRegisterMetaType< RenderParam >("RenderParam");
|
||||
|
||||
parseWorkbenchExtendedSelection(argc, argv);
|
||||
|
||||
QApplication application(argc, argv);
|
||||
|
||||
QApplication::setOrganizationDomain("local.qpdfview");
|
||||
QApplication::setOrganizationName("qpdfview");
|
||||
QApplication::setApplicationName("qpdfview");
|
||||
|
||||
QApplication::setApplicationVersion(APPLICATION_VERSION);
|
||||
|
||||
QApplication::setWindowIcon(QIcon(":icons/qpdfview"));
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
loadTranslators();
|
||||
|
||||
parseCommandLineArguments();
|
||||
|
||||
resolveSourceReferences();
|
||||
|
||||
activateUniqueInstance();
|
||||
|
||||
prepareSignalHandler();
|
||||
|
||||
mainWindow->show();
|
||||
mainWindow->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
foreach(const File& file, files)
|
||||
{
|
||||
mainWindow->jumpToPageOrOpenInNewTab(file.filePath, file.page, true, file.enclosingBox, quiet);
|
||||
}
|
||||
|
||||
if(!files.isEmpty())
|
||||
{
|
||||
mainWindow->saveDatabase();
|
||||
}
|
||||
|
||||
if(!searchText.isEmpty())
|
||||
{
|
||||
mainWindow->startSearch(searchText);
|
||||
}
|
||||
|
||||
return application.exec();
|
||||
}
|
3887
sources/mainwindow.cpp
Parasts fails
3887
sources/mainwindow.cpp
Parasts fails
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
587
sources/mainwindow.h
Parasts fails
587
sources/mainwindow.h
Parasts fails
@ -0,0 +1,587 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2012-2018 Adam Reichold
|
||||
Copyright 2018 Pavel Sanda
|
||||
Copyright 2012 Michał Trybus
|
||||
Copyright 2012 Alexander Volkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
#ifdef WITH_DBUS
|
||||
|
||||
#include <QDBusAbstractAdaptor>
|
||||
|
||||
class QDBusInterface;
|
||||
|
||||
#endif // WITH_DBUS
|
||||
|
||||
class QCheckBox;
|
||||
class QDateTime;
|
||||
class QGraphicsView;
|
||||
class QFileInfo;
|
||||
class QModelIndex;
|
||||
class QShortcut;
|
||||
class QTableView;
|
||||
class QToolButton;
|
||||
class QTreeView;
|
||||
class QWidgetAction;
|
||||
|
||||
#include "renderparam.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class Settings;
|
||||
class DocumentView;
|
||||
class TabWidget;
|
||||
class TreeView;
|
||||
class ComboBox;
|
||||
class MappingSpinBox;
|
||||
class SearchLineEdit;
|
||||
class SearchableMenu;
|
||||
class RecentlyUsedMenu;
|
||||
class RecentlyClosedMenu;
|
||||
class BookmarkModel;
|
||||
class Database;
|
||||
class ShortcutHandler;
|
||||
class SearchModel;
|
||||
class HelpDialog;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class MainWindowAdaptor;
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent = 0);
|
||||
|
||||
QSize sizeHint() const;
|
||||
QMenu* createPopupMenu();
|
||||
|
||||
public slots:
|
||||
void show();
|
||||
|
||||
bool open(const QString& filePath, int page = -1, const QRectF& highlight = QRectF(), bool quiet = false);
|
||||
bool openInNewTab(const QString& filePath, int page = -1, const QRectF& highlight = QRectF(), bool quiet = false);
|
||||
|
||||
bool jumpToPageOrOpenInNewTab(const QString& filePath, int page = -1, bool refreshBeforeJump = false, const QRectF& highlight = QRectF(), bool quiet = false);
|
||||
|
||||
void startSearch(const QString& text);
|
||||
|
||||
void saveDatabase();
|
||||
|
||||
protected slots:
|
||||
void on_tabWidget_currentChanged();
|
||||
void on_tabWidget_tabCloseRequested(int index);
|
||||
void on_tabWidget_tabDragRequested(int index);
|
||||
void on_tabWidget_tabContextMenuRequested(QPoint globalPos, int index);
|
||||
|
||||
void on_currentTab_documentChanged();
|
||||
void on_currentTab_documentModified();
|
||||
|
||||
void on_currentTab_numberOfPagesChaned(int numberOfPages);
|
||||
void on_currentTab_currentPageChanged(int currentPage);
|
||||
|
||||
void on_currentTab_canJumpChanged(bool backward, bool forward);
|
||||
|
||||
void on_currentTab_continuousModeChanged(bool continuousMode);
|
||||
void on_currentTab_layoutModeChanged(LayoutMode layoutMode);
|
||||
void on_currentTab_rightToLeftModeChanged(bool rightToLeftMode);
|
||||
void on_currentTab_scaleModeChanged(ScaleMode scaleMode);
|
||||
void on_currentTab_scaleFactorChanged(qreal scaleFactor);
|
||||
void on_currentTab_rotationChanged(Rotation rotation);
|
||||
|
||||
void on_currentTab_linkClicked(int page);
|
||||
void on_currentTab_linkClicked(bool newTab, const QString& filePath, int page);
|
||||
|
||||
void on_currentTab_renderFlagsChanged(qpdfview::RenderFlags renderFlags);
|
||||
|
||||
void on_currentTab_invertColorsChanged(bool invertColors);
|
||||
void on_currentTab_convertToGrayscaleChanged(bool convertToGrayscale);
|
||||
void on_currentTab_trimMarginsChanged(bool trimMargins);
|
||||
|
||||
void on_currentTab_compositionModeChanged(CompositionMode compositionMode);
|
||||
|
||||
void on_currentTab_highlightAllChanged(bool highlightAll);
|
||||
void on_currentTab_rubberBandModeChanged(RubberBandMode rubberBandMode);
|
||||
|
||||
void on_currentTab_searchFinished();
|
||||
void on_currentTab_searchProgressChanged(int progress);
|
||||
|
||||
void on_currentTab_customContextMenuRequested(QPoint pos);
|
||||
|
||||
void on_splitView_splitHorizontally_triggered();
|
||||
void on_splitView_splitVertically_triggered();
|
||||
void on_splitView_split_triggered(Qt::Orientation orientation, int index);
|
||||
void on_splitView_closeCurrent_triggered();
|
||||
void on_splitView_closeCurrent_triggered(int index);
|
||||
void on_splitView_currentWidgetChanged(QWidget* currentWidget);
|
||||
|
||||
void on_currentPage_editingFinished();
|
||||
void on_currentPage_returnPressed();
|
||||
|
||||
void on_scaleFactor_activated(int index);
|
||||
void on_scaleFactor_editingFinished();
|
||||
void on_scaleFactor_returnPressed();
|
||||
|
||||
void on_open_triggered();
|
||||
void on_openInNewTab_triggered();
|
||||
void on_openCopyInNewTab_triggered();
|
||||
void on_openCopyInNewTab_triggered(const DocumentView* tab);
|
||||
void on_openCopyInNewWindow_triggered();
|
||||
void on_openCopyInNewWindow_triggered(const DocumentView* tab);
|
||||
void on_openContainingFolder_triggered();
|
||||
void on_openContainingFolder_triggered(const DocumentView* tab);
|
||||
void on_moveToInstance_triggered();
|
||||
void on_moveToInstance_triggered(DocumentView* tab);
|
||||
void on_refresh_triggered();
|
||||
void on_save_triggered();
|
||||
void on_saveAs_triggered();
|
||||
void on_saveCopy_triggered();
|
||||
void on_print_triggered();
|
||||
|
||||
void on_recentlyUsed_openTriggered(const QString& filePath);
|
||||
|
||||
void on_previousPage_triggered();
|
||||
void on_nextPage_triggered();
|
||||
void on_firstPage_triggered();
|
||||
void on_lastPage_triggered();
|
||||
|
||||
void on_setFirstPage_triggered();
|
||||
|
||||
void on_jumpToPage_triggered();
|
||||
|
||||
void on_jumpBackward_triggered();
|
||||
void on_jumpForward_triggered();
|
||||
|
||||
void on_search_triggered();
|
||||
void on_findPrevious_triggered();
|
||||
void on_findNext_triggered();
|
||||
void on_cancelSearch_triggered();
|
||||
|
||||
void on_copyToClipboardMode_triggered(bool checked);
|
||||
void on_addAnnotationMode_triggered(bool checked);
|
||||
|
||||
void on_settings_triggered();
|
||||
|
||||
void on_continuousMode_triggered(bool checked);
|
||||
void on_twoPagesMode_triggered(bool checked);
|
||||
void on_twoPagesWithCoverPageMode_triggered(bool checked);
|
||||
void on_multiplePagesMode_triggered(bool checked);
|
||||
|
||||
void on_rightToLeftMode_triggered(bool checked);
|
||||
|
||||
void on_zoomIn_triggered();
|
||||
void on_zoomOut_triggered();
|
||||
void on_originalSize_triggered();
|
||||
|
||||
void on_fitToPageWidthMode_triggered(bool checked);
|
||||
void on_fitToPageSizeMode_triggered(bool checked);
|
||||
|
||||
void on_rotateLeft_triggered();
|
||||
void on_rotateRight_triggered();
|
||||
|
||||
void on_invertColors_triggered(bool checked);
|
||||
void on_convertToGrayscale_triggered(bool checked);
|
||||
void on_trimMargins_triggered(bool checked);
|
||||
void on_darkenWithPaperColor_triggered(bool checked);
|
||||
void on_lightenWithPaperColor_triggered(bool checked);
|
||||
|
||||
void on_fonts_triggered();
|
||||
|
||||
void on_fullscreen_triggered(bool checked);
|
||||
void on_presentation_triggered();
|
||||
|
||||
void on_previousTab_triggered();
|
||||
void on_nextTab_triggered();
|
||||
void on_closeTab_triggered();
|
||||
void on_closeAllTabs_triggered();
|
||||
void on_closeAllTabsButCurrentTab_triggered();
|
||||
void on_closeAllTabsButThisOne_triggered(int thisIndex);
|
||||
void on_closeAllTabsToTheLeft_triggered(int ofIndex);
|
||||
void on_closeAllTabsToTheRight_triggered(int ofIndex);
|
||||
void on_closeTabs_triggered(const QVector< DocumentView* >& tabs);
|
||||
|
||||
void on_restoreMostRecentlyClosedTab_triggered();
|
||||
|
||||
void on_recentlyClosed_tabActionTriggered(QAction* tabAction);
|
||||
|
||||
void on_tabAction_triggered();
|
||||
void on_tabShortcut_activated();
|
||||
|
||||
void on_previousBookmark_triggered();
|
||||
void on_nextBookmark_triggered();
|
||||
void on_addBookmark_triggered();
|
||||
void on_removeBookmark_triggered();
|
||||
void on_removeAllBookmarks_triggered();
|
||||
|
||||
void on_bookmarksMenu_aboutToShow();
|
||||
|
||||
void on_bookmark_openTriggered(const QString& absoluteFilePath);
|
||||
void on_bookmark_openInNewTabTriggered(const QString& absoluteFilePath);
|
||||
void on_bookmark_jumpToPageTriggered(const QString& absoluteFilePath, int page);
|
||||
void on_bookmark_removeBookmarkTriggered(const QString& absoluteFilePath);
|
||||
|
||||
void on_contents_triggered();
|
||||
void on_about_triggered();
|
||||
|
||||
void on_focusCurrentPage_activated();
|
||||
void on_focusScaleFactor_activated();
|
||||
|
||||
void on_toggleToolBars_triggered(bool checked);
|
||||
void on_toggleMenuBar_triggered(bool checked);
|
||||
|
||||
void on_searchInitiated(const QString& text, bool modified);
|
||||
void on_highlightAll_clicked(bool checked);
|
||||
|
||||
void on_dock_dockLocationChanged(Qt::DockWidgetArea area);
|
||||
|
||||
void on_outline_sectionCountChanged();
|
||||
void on_outline_clicked(const QModelIndex& index);
|
||||
|
||||
void on_properties_sectionCountChanged();
|
||||
|
||||
void on_thumbnails_dockLocationChanged(Qt::DockWidgetArea area);
|
||||
void on_thumbnails_verticalScrollBar_valueChanged(int value);
|
||||
|
||||
void on_bookmarks_sectionCountChanged();
|
||||
void on_bookmarks_clicked(const QModelIndex& index);
|
||||
void on_bookmarks_contextMenuRequested(QPoint pos);
|
||||
|
||||
void on_search_sectionCountChanged();
|
||||
void on_search_dockLocationChanged(Qt::DockWidgetArea area);
|
||||
void on_search_visibilityChanged(bool visible);
|
||||
void on_search_clicked(const QModelIndex& index);
|
||||
void on_search_rowsInserted(const QModelIndex& parent, int first, int last);
|
||||
|
||||
void on_saveDatabase_timeout();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* target, QEvent* event);
|
||||
|
||||
void closeEvent(QCloseEvent* event);
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent* event);
|
||||
void dropEvent(QDropEvent* event);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(MainWindow)
|
||||
|
||||
static Settings* s_settings;
|
||||
static Database* s_database;
|
||||
static ShortcutHandler* s_shortcutHandler;
|
||||
static SearchModel* s_searchModel;
|
||||
|
||||
void prepareStyle();
|
||||
|
||||
TabWidget* m_tabWidget;
|
||||
|
||||
DocumentView* currentTab() const;
|
||||
DocumentView* currentTab(int index) const;
|
||||
QVector< DocumentView* > allTabs(int index) const;
|
||||
QVector< DocumentView* > allTabs() const;
|
||||
|
||||
bool senderIsCurrentTab() const;
|
||||
|
||||
bool m_currentTabChangedBlocked;
|
||||
|
||||
class CurrentTabChangeBlocker;
|
||||
|
||||
void addTab(DocumentView* tab);
|
||||
void addTabAction(DocumentView* tab);
|
||||
void connectTab(DocumentView* tab);
|
||||
|
||||
void restorePerFileSettings(DocumentView* tab);
|
||||
|
||||
bool saveModifications(DocumentView* tab);
|
||||
void closeTab(DocumentView* tab);
|
||||
|
||||
void setWindowTitleForCurrentTab();
|
||||
void setCurrentPageSuffixForCurrentTab();
|
||||
|
||||
BookmarkModel* bookmarkModelForCurrentTab(bool create = false);
|
||||
|
||||
QAction* sourceLinkActionForCurrentTab(QObject* parent, QPoint pos);
|
||||
|
||||
class RestoreTab;
|
||||
|
||||
QTimer* m_saveDatabaseTimer;
|
||||
|
||||
void prepareDatabase();
|
||||
|
||||
void scheduleSaveDatabase();
|
||||
void scheduleSaveTabs();
|
||||
void scheduleSaveBookmarks();
|
||||
void scheduleSavePerFileSettings();
|
||||
|
||||
class TextValueMapper;
|
||||
|
||||
MappingSpinBox* m_currentPageSpinBox;
|
||||
QWidgetAction* m_currentPageAction;
|
||||
|
||||
ComboBox* m_scaleFactorComboBox;
|
||||
QWidgetAction* m_scaleFactorAction;
|
||||
|
||||
SearchLineEdit* m_searchLineEdit;
|
||||
QCheckBox* m_matchCaseCheckBox;
|
||||
QCheckBox* m_wholeWordsCheckBox;
|
||||
QCheckBox* m_highlightAllCheckBox;
|
||||
QToolButton* m_findPreviousButton;
|
||||
QToolButton* m_findNextButton;
|
||||
QToolButton* m_cancelSearchButton;
|
||||
|
||||
void createWidgets();
|
||||
|
||||
QAction* m_openAction;
|
||||
QAction* m_openInNewTabAction;
|
||||
QAction* m_refreshAction;
|
||||
QAction* m_saveAction;
|
||||
QAction* m_saveAsAction;
|
||||
QAction* m_saveCopyAction;
|
||||
QAction* m_printAction;
|
||||
QAction* m_exitAction;
|
||||
|
||||
QAction* m_previousPageAction;
|
||||
QAction* m_nextPageAction;
|
||||
QAction* m_firstPageAction;
|
||||
QAction* m_lastPageAction;
|
||||
|
||||
QAction* m_setFirstPageAction;
|
||||
|
||||
QAction* m_jumpToPageAction;
|
||||
|
||||
QAction* m_jumpBackwardAction;
|
||||
QAction* m_jumpForwardAction;
|
||||
|
||||
QAction* m_searchAction;
|
||||
QAction* m_findPreviousAction;
|
||||
QAction* m_findNextAction;
|
||||
QAction* m_cancelSearchAction;
|
||||
|
||||
QAction* m_copyToClipboardModeAction;
|
||||
QAction* m_addAnnotationModeAction;
|
||||
|
||||
QAction* m_settingsAction;
|
||||
|
||||
QAction* m_continuousModeAction;
|
||||
QAction* m_twoPagesModeAction;
|
||||
QAction* m_twoPagesWithCoverPageModeAction;
|
||||
QAction* m_multiplePagesModeAction;
|
||||
|
||||
QAction* m_rightToLeftModeAction;
|
||||
|
||||
QAction* m_zoomInAction;
|
||||
QAction* m_zoomOutAction;
|
||||
QAction* m_originalSizeAction;
|
||||
|
||||
QAction* m_fitToPageWidthModeAction;
|
||||
QAction* m_fitToPageSizeModeAction;
|
||||
|
||||
QAction* m_rotateLeftAction;
|
||||
QAction* m_rotateRightAction;
|
||||
|
||||
QAction* m_invertColorsAction;
|
||||
QAction* m_convertToGrayscaleAction;
|
||||
QAction* m_trimMarginsAction;
|
||||
QAction* m_darkenWithPaperColorAction;
|
||||
QAction* m_lightenWithPaperColorAction;
|
||||
|
||||
QAction* m_fontsAction;
|
||||
|
||||
QAction* m_fullscreenAction;
|
||||
QAction* m_presentationAction;
|
||||
|
||||
QAction* m_previousTabAction;
|
||||
QAction* m_nextTabAction;
|
||||
|
||||
QAction* m_closeTabAction;
|
||||
QAction* m_closeAllTabsAction;
|
||||
QAction* m_closeAllTabsButCurrentTabAction;
|
||||
|
||||
QAction* m_restoreMostRecentlyClosedTabAction;
|
||||
|
||||
QShortcut* m_tabShortcuts[9];
|
||||
|
||||
QAction* m_previousBookmarkAction;
|
||||
QAction* m_nextBookmarkAction;
|
||||
|
||||
QAction* m_addBookmarkAction;
|
||||
QAction* m_removeBookmarkAction;
|
||||
QAction* m_removeAllBookmarksAction;
|
||||
|
||||
QAction* m_contentsAction;
|
||||
QAction* m_aboutAction;
|
||||
|
||||
QAction* m_openCopyInNewTabAction;
|
||||
QAction* m_openCopyInNewWindowAction;
|
||||
QAction* m_openContainingFolderAction;
|
||||
QAction* m_moveToInstanceAction;
|
||||
QAction* m_splitViewHorizontallyAction;
|
||||
QAction* m_splitViewVerticallyAction;
|
||||
QAction* m_closeCurrentViewAction;
|
||||
|
||||
QAction* createAction(const QString& text, const QString& objectName, const QIcon& icon, const QList< QKeySequence >& shortcuts, const char* member, bool checkable = false, bool checked = false);
|
||||
QAction* createAction(const QString& text, const QString& objectName, const QIcon& icon, const QKeySequence& shortcut, const char* member, bool checkable = false, bool checked = false);
|
||||
QAction* createAction(const QString& text, const QString& objectName, const QString& iconName, const QList< QKeySequence >& shortcuts, const char* member, bool checkable = false, bool checked = false);
|
||||
QAction* createAction(const QString& text, const QString& objectName, const QString& iconName, const QKeySequence& shortcut, const char* member, bool checkable = false, bool checked = false);
|
||||
|
||||
void createActions();
|
||||
|
||||
QToolBar* m_fileToolBar;
|
||||
QToolBar* m_editToolBar;
|
||||
QToolBar* m_viewToolBar;
|
||||
|
||||
QShortcut* m_focusCurrentPageShortcut;
|
||||
QShortcut* m_focusScaleFactorShortcut;
|
||||
|
||||
QToolBar* createToolBar(const QString& text, const QString& objectName, const QStringList& actionNames, const QList< QAction* >& actions);
|
||||
|
||||
void createToolBars();
|
||||
|
||||
QDockWidget* m_outlineDock;
|
||||
TreeView* m_outlineView;
|
||||
|
||||
QDockWidget* m_propertiesDock;
|
||||
QTableView* m_propertiesView;
|
||||
|
||||
QDockWidget* m_thumbnailsDock;
|
||||
QGraphicsView* m_thumbnailsView;
|
||||
|
||||
QDockWidget* m_bookmarksDock;
|
||||
QTableView* m_bookmarksView;
|
||||
|
||||
QDockWidget* m_searchDock;
|
||||
QTreeView* m_searchView;
|
||||
QWidget* m_searchWidget;
|
||||
|
||||
QDockWidget* createDock(const QString& text, const QString& objectName, const QKeySequence& toggleViewShortcut);
|
||||
|
||||
void createSearchDock();
|
||||
|
||||
void createDocks();
|
||||
|
||||
QMenu* m_fileMenu;
|
||||
RecentlyUsedMenu* m_recentlyUsedMenu;
|
||||
QMenu* m_editMenu;
|
||||
QMenu* m_viewMenu;
|
||||
QMenu* m_compositionModeMenu;
|
||||
SearchableMenu* m_tabsMenu;
|
||||
RecentlyClosedMenu* m_recentlyClosedMenu;
|
||||
SearchableMenu* m_bookmarksMenu;
|
||||
QMenu* m_helpMenu;
|
||||
|
||||
bool m_bookmarksMenuIsDirty;
|
||||
|
||||
void createMenus();
|
||||
|
||||
int m_tabBarHadPolicy;
|
||||
|
||||
bool m_fileToolBarWasVisible;
|
||||
bool m_editToolBarWasVisible;
|
||||
bool m_viewToolBarWasVisible;
|
||||
|
||||
QAction* m_toggleToolBarsAction;
|
||||
QAction* m_toggleMenuBarAction;
|
||||
|
||||
QPointer< HelpDialog > m_helpDialog;
|
||||
|
||||
};
|
||||
|
||||
#ifdef WITH_DBUS
|
||||
|
||||
class MainWindowAdaptor : public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "local.qpdfview.MainWindow")
|
||||
|
||||
explicit MainWindowAdaptor(MainWindow* mainWindow);
|
||||
|
||||
public:
|
||||
static QDBusInterface* createInterface(const QString& instanceName = QString());
|
||||
static MainWindowAdaptor* createAdaptor(MainWindow* mainWindow);
|
||||
|
||||
public slots:
|
||||
Q_NOREPLY void raiseAndActivate();
|
||||
|
||||
bool open(const QString& absoluteFilePath, int page = -1, const QRectF& highlight = QRectF(), bool quiet = false);
|
||||
bool openInNewTab(const QString& absoluteFilePath, int page = -1, const QRectF& highlight = QRectF(), bool quiet = false);
|
||||
|
||||
bool jumpToPageOrOpenInNewTab(const QString& absoluteFilePath, int page = -1, bool refreshBeforeJump = false, const QRectF& highlight = QRectF(), bool quiet = false);
|
||||
|
||||
Q_NOREPLY void startSearch(const QString& text);
|
||||
|
||||
Q_NOREPLY void saveDatabase();
|
||||
|
||||
|
||||
int currentPage() const;
|
||||
Q_NOREPLY void jumpToPage(int page);
|
||||
|
||||
Q_NOREPLY void previousPage();
|
||||
Q_NOREPLY void nextPage();
|
||||
Q_NOREPLY void firstPage();
|
||||
Q_NOREPLY void lastPage();
|
||||
|
||||
Q_NOREPLY void previousBookmark();
|
||||
Q_NOREPLY void nextBookmark();
|
||||
|
||||
bool jumpToBookmark(const QString& label);
|
||||
|
||||
|
||||
Q_NOREPLY void continuousMode(bool checked);
|
||||
Q_NOREPLY void twoPagesMode(bool checked);
|
||||
Q_NOREPLY void twoPagesWithCoverPageMode(bool checked);
|
||||
Q_NOREPLY void multiplePagesMode(bool checked);
|
||||
|
||||
Q_NOREPLY void fitToPageWidthMode(bool checked);
|
||||
Q_NOREPLY void fitToPageSizeMode(bool checked);
|
||||
|
||||
Q_NOREPLY void invertColors(bool checked);
|
||||
Q_NOREPLY void convertToGrayscale(bool checked);
|
||||
Q_NOREPLY void trimMargins(bool checked);
|
||||
|
||||
Q_NOREPLY void fullscreen(bool checked);
|
||||
Q_NOREPLY void presentation();
|
||||
|
||||
|
||||
Q_NOREPLY void closeTab();
|
||||
Q_NOREPLY void closeAllTabs();
|
||||
Q_NOREPLY void closeAllTabsButCurrentTab();
|
||||
|
||||
bool closeTab(const QString& absoluteFilePath);
|
||||
|
||||
private:
|
||||
MainWindow* mainWindow() const;
|
||||
|
||||
static QString serviceName(QString instanceName = QString());
|
||||
|
||||
};
|
||||
|
||||
#endif // WITH_DBUS
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // MAINWINDOW_H
|
991
sources/miscellaneous.cpp
Parasts fails
991
sources/miscellaneous.cpp
Parasts fails
@ -0,0 +1,991 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2012-2018 Adam Reichold
|
||||
Copyright 2018 Pavel Sanda
|
||||
Copyright 2014 Dorian Scholz
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "miscellaneous.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QProcess>
|
||||
#include <QScrollBar>
|
||||
#include <QTimer>
|
||||
#include <QToolTip>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "searchmodel.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
inline bool isPrintable(const QString& string)
|
||||
{
|
||||
foreach(const QChar& character, string)
|
||||
{
|
||||
if(!character.isPrint())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline QModelIndex firstIndex(const QModelIndexList& indexes)
|
||||
{
|
||||
return !indexes.isEmpty() ? indexes.first() : QModelIndex();
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
GraphicsCompositionModeEffect::GraphicsCompositionModeEffect(QPainter::CompositionMode compositionMode, QObject* parent) : QGraphicsEffect(parent),
|
||||
m_compositionMode(compositionMode)
|
||||
{
|
||||
}
|
||||
|
||||
void GraphicsCompositionModeEffect::draw(QPainter* painter)
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->setCompositionMode(m_compositionMode);
|
||||
|
||||
drawSource(painter);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
ProxyStyle::ProxyStyle() : QProxyStyle(),
|
||||
m_scrollableMenus(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool ProxyStyle::scrollableMenus() const
|
||||
{
|
||||
return m_scrollableMenus;
|
||||
}
|
||||
|
||||
void ProxyStyle::setScrollableMenus(bool scrollableMenus)
|
||||
{
|
||||
m_scrollableMenus = scrollableMenus;
|
||||
}
|
||||
|
||||
int ProxyStyle::styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const
|
||||
{
|
||||
if(m_scrollableMenus && hint == QStyle::SH_Menu_Scrollable)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
||||
}
|
||||
|
||||
ToolTipMenu::ToolTipMenu(QWidget* parent) : QMenu(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ToolTipMenu::ToolTipMenu(const QString& title, QWidget* parent) : QMenu(title, parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool ToolTipMenu::event(QEvent* event)
|
||||
{
|
||||
const QAction* const action = activeAction();
|
||||
|
||||
if(event->type() == QEvent::ToolTip && action != 0 && !action->data().isNull())
|
||||
{
|
||||
QToolTip::showText(static_cast< QHelpEvent* >(event)->globalPos(), action->toolTip());
|
||||
}
|
||||
else
|
||||
{
|
||||
QToolTip::hideText();
|
||||
}
|
||||
|
||||
return QMenu::event(event);
|
||||
}
|
||||
|
||||
SearchableMenu::SearchableMenu(const QString& title, QWidget* parent) : ToolTipMenu(title, parent),
|
||||
m_searchable(false),
|
||||
m_text()
|
||||
{
|
||||
}
|
||||
|
||||
bool SearchableMenu::isSearchable() const
|
||||
{
|
||||
return m_searchable;
|
||||
}
|
||||
|
||||
void SearchableMenu::setSearchable(bool searchable)
|
||||
{
|
||||
m_searchable = searchable;
|
||||
}
|
||||
|
||||
void SearchableMenu::hideEvent(QHideEvent* event)
|
||||
{
|
||||
QMenu::hideEvent(event);
|
||||
|
||||
if(m_searchable && !event->spontaneous())
|
||||
{
|
||||
m_text = QString();
|
||||
|
||||
foreach(QAction* action, actions())
|
||||
{
|
||||
action->setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SearchableMenu::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if(!m_searchable)
|
||||
{
|
||||
QMenu::keyPressEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
const QString text = event->text();
|
||||
|
||||
if(!text.isEmpty() && isPrintable(text))
|
||||
{
|
||||
m_text.append(text);
|
||||
}
|
||||
else if(event->key() == Qt::Key_Backspace || event->key() == Qt::Key_Delete)
|
||||
{
|
||||
m_text.chop(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMenu::keyPressEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
QAction* firstVisibleAction = 0;
|
||||
|
||||
foreach(QAction* action, actions())
|
||||
{
|
||||
if(action->data().isNull()) // Modify only flagged actions
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool visible = action->text().contains(m_text, Qt::CaseInsensitive);
|
||||
|
||||
action->setVisible(visible);
|
||||
|
||||
if(visible && firstVisibleAction == 0)
|
||||
{
|
||||
firstVisibleAction = action;
|
||||
}
|
||||
}
|
||||
|
||||
setActiveAction(firstVisibleAction);
|
||||
|
||||
QToolTip::showText(mapToGlobal(rect().topLeft()), tr("Search for '%1'...").arg(m_text), this);
|
||||
}
|
||||
|
||||
TabBar::TabBar(QWidget* parent) : QTabBar(parent),
|
||||
m_dragIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
QSize TabBar::tabSizeHint(int index) const
|
||||
{
|
||||
QSize size = QTabBar::tabSizeHint(index);
|
||||
|
||||
const TabWidget* tabWidget = qobject_cast< TabWidget* >(parentWidget());
|
||||
|
||||
if(tabWidget != 0 && tabWidget->spreadTabs())
|
||||
{
|
||||
switch(tabWidget->tabPosition())
|
||||
{
|
||||
default:
|
||||
case QTabWidget::North:
|
||||
case QTabWidget::South:
|
||||
size.setWidth(qMax(width() / count(), size.width()));
|
||||
break;
|
||||
case QTabWidget::East:
|
||||
case QTabWidget::West:
|
||||
size.setHeight(qMax(height() / count(), size.height()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void TabBar::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if(event->button() == Qt::MidButton)
|
||||
{
|
||||
const int index = tabAt(event->pos());
|
||||
|
||||
if(index != -1)
|
||||
{
|
||||
emit tabCloseRequested(index);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(event->modifiers() == Qt::ShiftModifier && event->button() == Qt::LeftButton)
|
||||
{
|
||||
const int index = tabAt(event->pos());
|
||||
|
||||
if(index != -1)
|
||||
{
|
||||
m_dragIndex = index;
|
||||
m_dragPos = event->pos();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QTabBar::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void TabBar::mouseMoveEvent(QMouseEvent* event)
|
||||
{
|
||||
QTabBar::mouseMoveEvent(event);
|
||||
|
||||
if(m_dragIndex != -1)
|
||||
{
|
||||
if((event->pos() - m_dragPos).manhattanLength() >= QApplication::startDragDistance())
|
||||
{
|
||||
emit tabDragRequested(m_dragIndex);
|
||||
|
||||
m_dragIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TabBar::mouseReleaseEvent(QMouseEvent* event)
|
||||
{
|
||||
QTabBar::mouseReleaseEvent(event);
|
||||
|
||||
m_dragIndex = -1;
|
||||
}
|
||||
|
||||
TabWidget::TabWidget(QWidget* parent) : QTabWidget(parent),
|
||||
m_tabBarPolicy(TabBarAsNeeded),
|
||||
m_spreadTabs(false)
|
||||
{
|
||||
TabBar* tabBar = new TabBar(this);
|
||||
|
||||
tabBar->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
connect(tabBar, SIGNAL(tabDragRequested(int)), SIGNAL(tabDragRequested(int)));
|
||||
connect(tabBar, SIGNAL(customContextMenuRequested(QPoint)), SLOT(on_tabBar_customContextMenuRequested(QPoint)));
|
||||
|
||||
setTabBar(tabBar);
|
||||
}
|
||||
|
||||
int TabWidget::addTab(QWidget* const widget, const bool nextToCurrent,
|
||||
const QString& label, const QString& toolTip)
|
||||
{
|
||||
const int index = nextToCurrent
|
||||
? insertTab(currentIndex() + 1, widget, label)
|
||||
: QTabWidget::addTab(widget, label);
|
||||
|
||||
setTabToolTip(index, toolTip);
|
||||
setCurrentIndex(index);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
TabWidget::TabBarPolicy TabWidget::tabBarPolicy() const
|
||||
{
|
||||
return m_tabBarPolicy;
|
||||
}
|
||||
|
||||
void TabWidget::setTabBarPolicy(TabWidget::TabBarPolicy tabBarPolicy)
|
||||
{
|
||||
m_tabBarPolicy = tabBarPolicy;
|
||||
|
||||
switch(m_tabBarPolicy)
|
||||
{
|
||||
case TabBarAsNeeded:
|
||||
tabBar()->setVisible(count() > 1);
|
||||
break;
|
||||
case TabBarAlwaysOn:
|
||||
tabBar()->setVisible(true);
|
||||
break;
|
||||
case TabBarAlwaysOff:
|
||||
tabBar()->setVisible(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool TabWidget::spreadTabs() const
|
||||
{
|
||||
return m_spreadTabs;
|
||||
}
|
||||
|
||||
void TabWidget::setSpreadTabs(bool spreadTabs)
|
||||
{
|
||||
if(m_spreadTabs != spreadTabs)
|
||||
{
|
||||
m_spreadTabs = spreadTabs;
|
||||
|
||||
QResizeEvent resizeEvent(tabBar()->size(), tabBar()->size());
|
||||
QApplication::sendEvent(tabBar(), &resizeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void TabWidget::previousTab()
|
||||
{
|
||||
int index = currentIndex() - 1;
|
||||
|
||||
if(index < 0)
|
||||
{
|
||||
index = count() - 1;
|
||||
}
|
||||
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void TabWidget::nextTab()
|
||||
{
|
||||
int index = currentIndex() + 1;
|
||||
|
||||
if(index >= count())
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
|
||||
setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void TabWidget::on_tabBar_customContextMenuRequested(QPoint pos)
|
||||
{
|
||||
const int index = tabBar()->tabAt(pos);
|
||||
|
||||
if(index != -1)
|
||||
{
|
||||
emit tabContextMenuRequested(tabBar()->mapToGlobal(pos), tabBar()->tabAt(pos));
|
||||
}
|
||||
}
|
||||
|
||||
void TabWidget::tabInserted(int index)
|
||||
{
|
||||
QTabWidget::tabInserted(index);
|
||||
|
||||
if(m_tabBarPolicy == TabBarAsNeeded)
|
||||
{
|
||||
tabBar()->setVisible(count() > 1);
|
||||
}
|
||||
}
|
||||
|
||||
void TabWidget::tabRemoved(int index)
|
||||
{
|
||||
QTabWidget::tabRemoved(index);
|
||||
|
||||
if(m_tabBarPolicy == TabBarAsNeeded)
|
||||
{
|
||||
tabBar()->setVisible(count() > 1);
|
||||
}
|
||||
}
|
||||
|
||||
TreeView::TreeView(int expansionRole, QWidget* parent) : QTreeView(parent),
|
||||
m_expansionRole(expansionRole)
|
||||
{
|
||||
connect(this, SIGNAL(expanded(QModelIndex)), SLOT(on_expanded(QModelIndex)));
|
||||
connect(this, SIGNAL(collapsed(QModelIndex)), SLOT(on_collapsed(QModelIndex)));
|
||||
}
|
||||
|
||||
void TreeView::expandAbove(const QModelIndex& child)
|
||||
{
|
||||
for(QModelIndex index = child.parent(); index.isValid(); index = index.parent())
|
||||
{
|
||||
expand(index);
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::expandAll(const QModelIndex& index)
|
||||
{
|
||||
if(index.isValid())
|
||||
{
|
||||
if(!isExpanded(index))
|
||||
{
|
||||
expand(index);
|
||||
}
|
||||
|
||||
for(int row = 0, rowCount = model()->rowCount(index); row < rowCount; ++row)
|
||||
{
|
||||
expandAll(index.child(row, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTreeView::expandAll();
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::collapseAll(const QModelIndex& index)
|
||||
{
|
||||
if(index.isValid())
|
||||
{
|
||||
if(isExpanded(index))
|
||||
{
|
||||
collapse(index);
|
||||
}
|
||||
|
||||
for(int row = 0, rowCount = model()->rowCount(index); row < rowCount; ++row)
|
||||
{
|
||||
collapseAll(index.child(row, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QTreeView::collapseAll();
|
||||
}
|
||||
}
|
||||
|
||||
int TreeView::expandedDepth(const QModelIndex& index)
|
||||
{
|
||||
if(index.isValid())
|
||||
{
|
||||
if(!isExpanded(index) || !model()->hasChildren(index))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int depth = 0;
|
||||
|
||||
for(int row = 0, rowCount = model()->rowCount(index); row < rowCount; ++row)
|
||||
{
|
||||
depth = qMax(depth, expandedDepth(index.child(row, 0)));
|
||||
}
|
||||
|
||||
return 1 + depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
int depth = 0;
|
||||
|
||||
for(int row = 0, rowCount = model()->rowCount(); row < rowCount; ++row)
|
||||
{
|
||||
depth = qMax(depth, expandedDepth(model()->index(row, 0)));
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::expandToDepth(const QModelIndex& index, int depth)
|
||||
{
|
||||
if(index.isValid())
|
||||
{
|
||||
if(depth > 0)
|
||||
{
|
||||
if(!isExpanded(index))
|
||||
{
|
||||
expand(index);
|
||||
}
|
||||
}
|
||||
|
||||
if(depth > 1)
|
||||
{
|
||||
for(int row = 0, rowCount = model()->rowCount(index); row < rowCount; ++row)
|
||||
{
|
||||
expandToDepth(index.child(row, 0), depth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int row = 0, rowCount = model()->rowCount(); row < rowCount; ++row)
|
||||
{
|
||||
expandToDepth(model()->index(row, 0), depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::collapseFromDepth(const QModelIndex& index, int depth)
|
||||
{
|
||||
if(index.isValid())
|
||||
{
|
||||
if(depth <= 0)
|
||||
{
|
||||
if(isExpanded(index))
|
||||
{
|
||||
collapse(index);
|
||||
}
|
||||
}
|
||||
|
||||
for(int row = 0, rowCount = model()->rowCount(index); row < rowCount; ++row)
|
||||
{
|
||||
collapseFromDepth(index.child(row, 0), depth - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int row = 0, rowCount = model()->rowCount(); row < rowCount; ++row)
|
||||
{
|
||||
collapseFromDepth(model()->index(row, 0), depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::restoreExpansion(const QModelIndex& index)
|
||||
{
|
||||
if(index.isValid())
|
||||
{
|
||||
const bool expanded = index.data(m_expansionRole).toBool();
|
||||
|
||||
if(isExpanded(index) != expanded)
|
||||
{
|
||||
setExpanded(index, expanded);
|
||||
}
|
||||
}
|
||||
|
||||
for(int row = 0, rowCount = model()->rowCount(index); row < rowCount; ++row)
|
||||
{
|
||||
restoreExpansion(model()->index(row, 0, index));
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
const bool verticalKeys = event->key() == Qt::Key_Up || event->key() == Qt::Key_Down;
|
||||
const bool horizontalKeys = event->key() == Qt::Key_Left || event->key() == Qt::Key_Right;
|
||||
|
||||
const QModelIndex selection = firstIndex(selectedIndexes());
|
||||
|
||||
// If Shift is pressed, the view is scrolled up or down.
|
||||
if(event->modifiers().testFlag(Qt::ShiftModifier) && verticalKeys)
|
||||
{
|
||||
QScrollBar* scrollBar = verticalScrollBar();
|
||||
|
||||
if(event->key() == Qt::Key_Up && scrollBar->value() > scrollBar->minimum())
|
||||
{
|
||||
scrollBar->triggerAction(QAbstractSlider::SliderSingleStepSub);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
else if(event->key() == Qt::Key_Down && scrollBar->value() < scrollBar->maximum())
|
||||
{
|
||||
scrollBar->triggerAction(QAbstractSlider::SliderSingleStepAdd);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If Control is pressed, all children of the selected item are expanded or collapsed.
|
||||
if(event->modifiers().testFlag(Qt::ControlModifier) && horizontalKeys)
|
||||
{
|
||||
if(event->key() == Qt::Key_Left)
|
||||
{
|
||||
collapseAll(selection);
|
||||
}
|
||||
else if(event->key() == Qt::Key_Right)
|
||||
{
|
||||
expandAll(selection);
|
||||
}
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
// If Shift is pressed, one level of children of the selected item are expanded or collapsed.
|
||||
if(event->modifiers().testFlag(Qt::ShiftModifier) && horizontalKeys)
|
||||
{
|
||||
const int depth = expandedDepth(selection);
|
||||
|
||||
if(event->key() == Qt::Key_Left)
|
||||
{
|
||||
collapseFromDepth(selection, depth - 1);
|
||||
}
|
||||
else if(event->key() == Qt::Key_Right)
|
||||
{
|
||||
expandToDepth(selection, depth + 1);
|
||||
}
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void TreeView::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
const QModelIndex selection = firstIndex(selectedIndexes());
|
||||
|
||||
// If Control is pressed, expand or collapse the selected entry.
|
||||
if(event->modifiers().testFlag(Qt::ControlModifier) && selection.isValid())
|
||||
{
|
||||
if(event->delta() > 0)
|
||||
{
|
||||
collapse(selection);
|
||||
}
|
||||
else
|
||||
{
|
||||
expand(selection);
|
||||
}
|
||||
|
||||
// Fall through when Shift is also pressed.
|
||||
if(!event->modifiers().testFlag(Qt::ShiftModifier))
|
||||
{
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If Shift is pressed, move the selected entry up and down.
|
||||
if(event->modifiers().testFlag(Qt::ShiftModifier) && selection.isValid())
|
||||
{
|
||||
QModelIndex sibling;
|
||||
|
||||
if(event->delta() > 0)
|
||||
{
|
||||
sibling = indexAbove(selection);
|
||||
}
|
||||
else
|
||||
{
|
||||
sibling = indexBelow(selection);
|
||||
}
|
||||
|
||||
if(sibling.isValid())
|
||||
{
|
||||
setCurrentIndex(sibling);
|
||||
}
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QTreeView::wheelEvent(event);
|
||||
}
|
||||
|
||||
void TreeView::contextMenuEvent(QContextMenuEvent* event)
|
||||
{
|
||||
QTreeView::contextMenuEvent(event);
|
||||
|
||||
if(!event->isAccepted())
|
||||
{
|
||||
QMenu menu;
|
||||
|
||||
const QAction* expandAllAction = menu.addAction(tr("&Expand all"));
|
||||
const QAction* collapseAllAction = menu.addAction(tr("&Collapse all"));
|
||||
|
||||
const QAction* action = menu.exec(event->globalPos());
|
||||
|
||||
if(action == expandAllAction)
|
||||
{
|
||||
expandAll(indexAt(event->pos()));
|
||||
}
|
||||
else if(action == collapseAllAction)
|
||||
{
|
||||
collapseAll(indexAt(event->pos()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TreeView::on_expanded(const QModelIndex& index)
|
||||
{
|
||||
model()->setData(index, true, m_expansionRole);
|
||||
}
|
||||
|
||||
void TreeView::on_collapsed(const QModelIndex& index)
|
||||
{
|
||||
model()->setData(index, false, m_expansionRole);
|
||||
}
|
||||
|
||||
LineEdit::LineEdit(QWidget* parent) : QLineEdit(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void LineEdit::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
QLineEdit::mousePressEvent(event);
|
||||
|
||||
selectAll();
|
||||
}
|
||||
|
||||
ComboBox::ComboBox(QWidget* parent) : QComboBox(parent)
|
||||
{
|
||||
setLineEdit(new LineEdit(this));
|
||||
}
|
||||
|
||||
SpinBox::SpinBox(QWidget* parent) : QSpinBox(parent)
|
||||
{
|
||||
setLineEdit(new LineEdit(this));
|
||||
}
|
||||
|
||||
void SpinBox::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
QSpinBox::keyPressEvent(event);
|
||||
|
||||
if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
||||
{
|
||||
emit returnPressed();
|
||||
}
|
||||
}
|
||||
|
||||
MappingSpinBox::MappingSpinBox(TextValueMapper* mapper, QWidget* parent) : SpinBox(parent),
|
||||
m_mapper(mapper)
|
||||
{
|
||||
}
|
||||
|
||||
QString MappingSpinBox::textFromValue(int val) const
|
||||
{
|
||||
bool ok = false;
|
||||
QString text = m_mapper->textFromValue(val, ok);
|
||||
|
||||
if(!ok)
|
||||
{
|
||||
text = SpinBox::textFromValue(val);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
int MappingSpinBox::valueFromText(const QString& text) const
|
||||
{
|
||||
bool ok = false;
|
||||
int value = m_mapper->valueFromText(text, ok);
|
||||
|
||||
if(!ok)
|
||||
{
|
||||
value = SpinBox::valueFromText(text);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QValidator::State MappingSpinBox::validate(QString& input, int& pos) const
|
||||
{
|
||||
Q_UNUSED(input);
|
||||
Q_UNUSED(pos);
|
||||
|
||||
return QValidator::Acceptable;
|
||||
}
|
||||
|
||||
int getMappedNumber(MappingSpinBox::TextValueMapper* mapper,
|
||||
QWidget* parent, const QString& title, const QString& caption,
|
||||
int value, int min, int max, bool* ok, Qt::WindowFlags flags)
|
||||
{
|
||||
QDialog* dialog = new QDialog(parent, flags | Qt::MSWindowsFixedSizeDialogHint);
|
||||
dialog->setWindowTitle(title);
|
||||
|
||||
QLabel* label = new QLabel(dialog);
|
||||
label->setText(caption);
|
||||
|
||||
MappingSpinBox* mappingSpinBox = new MappingSpinBox(mapper, dialog);
|
||||
mappingSpinBox->setRange(min, max);
|
||||
mappingSpinBox->setValue(value);
|
||||
mappingSpinBox->selectAll();
|
||||
|
||||
QDialogButtonBox* dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, dialog);
|
||||
QObject::connect(dialogButtonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
|
||||
QObject::connect(dialogButtonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
|
||||
|
||||
dialog->setLayout(new QVBoxLayout(dialog));
|
||||
dialog->layout()->addWidget(label);
|
||||
dialog->layout()->addWidget(mappingSpinBox);
|
||||
dialog->layout()->addWidget(dialogButtonBox);
|
||||
|
||||
dialog->setFocusProxy(mappingSpinBox);
|
||||
|
||||
const int dialogResult = dialog->exec();
|
||||
const int number = mappingSpinBox->value();
|
||||
|
||||
delete dialog;
|
||||
|
||||
if(ok)
|
||||
{
|
||||
*ok = dialogResult == QDialog::Accepted;
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
ProgressLineEdit::ProgressLineEdit(QWidget* parent) : QLineEdit(parent),
|
||||
m_progress(0)
|
||||
{
|
||||
}
|
||||
|
||||
int ProgressLineEdit::progress() const
|
||||
{
|
||||
return m_progress;
|
||||
}
|
||||
|
||||
void ProgressLineEdit::setProgress(int progress)
|
||||
{
|
||||
if(m_progress != progress && progress >= 0 && progress <= 100)
|
||||
{
|
||||
m_progress = progress;
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ProgressLineEdit::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
QLineEdit::paintEvent(event);
|
||||
|
||||
QPainter painter(this);
|
||||
|
||||
QRect highlightedRect = rect();
|
||||
highlightedRect.setWidth(m_progress * highlightedRect.width() / 100);
|
||||
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Multiply);
|
||||
painter.fillRect(highlightedRect, palette().highlight());
|
||||
}
|
||||
|
||||
void ProgressLineEdit::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
QLineEdit::keyPressEvent(event);
|
||||
|
||||
if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
|
||||
{
|
||||
emit returnPressed(event->modifiers());
|
||||
}
|
||||
}
|
||||
|
||||
SearchLineEdit::SearchLineEdit(QWidget* parent) : ProgressLineEdit(parent)
|
||||
{
|
||||
m_timer = new QTimer(this);
|
||||
|
||||
m_timer->setInterval(2000);
|
||||
m_timer->setSingleShot(true);
|
||||
|
||||
connect(this, SIGNAL(textEdited(QString)), m_timer, SLOT(start()));
|
||||
connect(this, SIGNAL(returnPressed(Qt::KeyboardModifiers)), SLOT(on_returnPressed(Qt::KeyboardModifiers)));
|
||||
connect(m_timer, SIGNAL(timeout()), SLOT(on_timeout()));
|
||||
}
|
||||
|
||||
void SearchLineEdit::startSearch()
|
||||
{
|
||||
QTimer::singleShot(0, this, SLOT(on_timeout()));
|
||||
}
|
||||
|
||||
void SearchLineEdit::startTimer()
|
||||
{
|
||||
m_timer->start();
|
||||
}
|
||||
|
||||
void SearchLineEdit::stopTimer()
|
||||
{
|
||||
m_timer->stop();
|
||||
}
|
||||
|
||||
void SearchLineEdit::on_timeout()
|
||||
{
|
||||
emit searchInitiated(text());
|
||||
}
|
||||
|
||||
void SearchLineEdit::on_returnPressed(Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
emit searchInitiated(text(), modifiers == Qt::ShiftModifier);
|
||||
}
|
||||
|
||||
Splitter::Splitter(Qt::Orientation orientation, QWidget* parent) : QSplitter(orientation, parent),
|
||||
m_currentIndex(0)
|
||||
{
|
||||
connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)), this, SLOT(on_focusChanged(QWidget*,QWidget*)));
|
||||
}
|
||||
|
||||
QWidget* Splitter::currentWidget() const
|
||||
{
|
||||
return widget(m_currentIndex);
|
||||
}
|
||||
|
||||
void Splitter::setCurrentWidget(QWidget* const currentWidget)
|
||||
{
|
||||
for(int index = 0, count = this->count(); index < count; ++index)
|
||||
{
|
||||
QWidget* const widget = this->widget(index);
|
||||
|
||||
if(currentWidget == widget)
|
||||
{
|
||||
if(m_currentIndex != index)
|
||||
{
|
||||
m_currentIndex = index;
|
||||
|
||||
emit currentWidgetChanged(currentWidget);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Splitter::setUniformSizes()
|
||||
{
|
||||
int size;
|
||||
|
||||
switch(orientation())
|
||||
{
|
||||
default:
|
||||
case Qt::Horizontal:
|
||||
size = width();
|
||||
break;
|
||||
case Qt::Vertical:
|
||||
size = height();
|
||||
break;
|
||||
}
|
||||
|
||||
QList< int > sizes;
|
||||
|
||||
for(int index = 0, count = this->count(); index < count; ++index)
|
||||
{
|
||||
sizes.append(size / count);
|
||||
}
|
||||
|
||||
setSizes(sizes);
|
||||
}
|
||||
|
||||
void Splitter::on_focusChanged(QWidget* /* old */, QWidget* now)
|
||||
{
|
||||
for(QWidget* currentWidget = now; currentWidget != 0; currentWidget = currentWidget->parentWidget())
|
||||
{
|
||||
if(currentWidget->parentWidget() == this)
|
||||
{
|
||||
setCurrentWidget(currentWidget);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void openInNewWindow(const QString& filePath, int page)
|
||||
{
|
||||
QProcess::startDetached(
|
||||
QApplication::applicationFilePath(),
|
||||
QStringList() << QString("%2#%1").arg(page).arg(filePath)
|
||||
);
|
||||
}
|
||||
|
||||
} // qpdfview
|
426
sources/miscellaneous.h
Parasts fails
426
sources/miscellaneous.h
Parasts fails
@ -0,0 +1,426 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2012-2018 Adam Reichold
|
||||
Copyright 2018 Pavel Sanda
|
||||
Copyright 2014 Dorian Scholz
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MISCELLANEOUS_H
|
||||
#define MISCELLANEOUS_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QGraphicsEffect>
|
||||
#include <QLineEdit>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
#include <QProxyStyle>
|
||||
#include <QSpinBox>
|
||||
#include <QSplitter>
|
||||
#include <QTreeView>
|
||||
|
||||
class QTextLayout;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
// graphics composition mode effect
|
||||
|
||||
class GraphicsCompositionModeEffect : public QGraphicsEffect
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GraphicsCompositionModeEffect(QPainter::CompositionMode compositionMode, QObject* parent = 0);
|
||||
|
||||
protected:
|
||||
void draw(QPainter* painter);
|
||||
|
||||
private:
|
||||
QPainter::CompositionMode m_compositionMode;
|
||||
|
||||
};
|
||||
|
||||
// proxy style
|
||||
|
||||
class ProxyStyle : public QProxyStyle
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ProxyStyle();
|
||||
|
||||
bool scrollableMenus() const;
|
||||
void setScrollableMenus(bool scrollableMenus);
|
||||
|
||||
int styleHint(StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ProxyStyle)
|
||||
|
||||
bool m_scrollableMenus;
|
||||
|
||||
};
|
||||
|
||||
// tool tip menu
|
||||
|
||||
class ToolTipMenu : public QMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ToolTipMenu(QWidget* parent = 0);
|
||||
ToolTipMenu(const QString& title, QWidget* parent = 0);
|
||||
|
||||
protected:
|
||||
bool event(QEvent* event);
|
||||
|
||||
};
|
||||
|
||||
// searchable menu
|
||||
|
||||
class SearchableMenu : public ToolTipMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SearchableMenu(const QString& title, QWidget* parent = 0);
|
||||
|
||||
bool isSearchable() const;
|
||||
void setSearchable(bool searchable);
|
||||
|
||||
protected:
|
||||
void hideEvent(QHideEvent* event);
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
private:
|
||||
bool m_searchable;
|
||||
QString m_text;
|
||||
|
||||
};
|
||||
|
||||
// tab bar
|
||||
|
||||
class TabBar : public QTabBar
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TabBar(QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void tabDragRequested(int index);
|
||||
|
||||
protected:
|
||||
QSize tabSizeHint(int index) const;
|
||||
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
void mouseReleaseEvent(QMouseEvent* event);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(TabBar)
|
||||
|
||||
int m_dragIndex;
|
||||
QPoint m_dragPos;
|
||||
|
||||
};
|
||||
|
||||
// tab widget
|
||||
|
||||
class TabWidget : public QTabWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TabWidget(QWidget* parent = 0);
|
||||
|
||||
bool hasCurrent() const { return currentIndex() != -1; }
|
||||
|
||||
QString currentTabText() const { return tabText(currentIndex()); }
|
||||
void setCurrentTabText(const QString& text) { setTabText(currentIndex(), text); }
|
||||
|
||||
QString currentTabToolTip() const { return tabToolTip(currentIndex()); }
|
||||
void setCurrentTabToolTip(const QString& toolTip) { setTabToolTip(currentIndex(), toolTip); }
|
||||
|
||||
int addTab(QWidget* const widget, const bool nextToCurrent,
|
||||
const QString& label, const QString& toolTip);
|
||||
|
||||
enum TabBarPolicy
|
||||
{
|
||||
TabBarAsNeeded = 0,
|
||||
TabBarAlwaysOn = 1,
|
||||
TabBarAlwaysOff = 2
|
||||
};
|
||||
|
||||
TabBarPolicy tabBarPolicy() const;
|
||||
void setTabBarPolicy(TabBarPolicy tabBarPolicy);
|
||||
|
||||
bool spreadTabs() const;
|
||||
void setSpreadTabs(bool spreadTabs);
|
||||
|
||||
public slots:
|
||||
void previousTab();
|
||||
void nextTab();
|
||||
|
||||
signals:
|
||||
void tabDragRequested(int index);
|
||||
void tabContextMenuRequested(QPoint globalPos, int index);
|
||||
|
||||
protected slots:
|
||||
void on_tabBar_customContextMenuRequested(QPoint pos);
|
||||
|
||||
protected:
|
||||
void tabInserted(int index);
|
||||
void tabRemoved(int index);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(TabWidget)
|
||||
|
||||
TabBarPolicy m_tabBarPolicy;
|
||||
bool m_spreadTabs;
|
||||
|
||||
};
|
||||
|
||||
// tree view
|
||||
|
||||
class TreeView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TreeView(int expansionRole, QWidget* parent = 0);
|
||||
|
||||
public slots:
|
||||
void expandAbove(const QModelIndex& child);
|
||||
|
||||
void expandAll(const QModelIndex& index = QModelIndex());
|
||||
void collapseAll(const QModelIndex& index = QModelIndex());
|
||||
|
||||
int expandedDepth(const QModelIndex& index);
|
||||
|
||||
void expandToDepth(const QModelIndex& index, int depth);
|
||||
void collapseFromDepth(const QModelIndex& index, int depth);
|
||||
|
||||
void restoreExpansion(const QModelIndex& index = QModelIndex());
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void wheelEvent(QWheelEvent* event);
|
||||
|
||||
void contextMenuEvent(QContextMenuEvent* event);
|
||||
|
||||
protected slots:
|
||||
void on_expanded(const QModelIndex& index);
|
||||
void on_collapsed(const QModelIndex& index);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(TreeView)
|
||||
|
||||
int m_expansionRole;
|
||||
|
||||
};
|
||||
|
||||
// line edit
|
||||
|
||||
class LineEdit : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LineEdit(QWidget* parent = 0);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(LineEdit)
|
||||
|
||||
};
|
||||
|
||||
// combo box
|
||||
|
||||
class ComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ComboBox(QWidget* parent = 0);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ComboBox)
|
||||
|
||||
};
|
||||
|
||||
// spin box
|
||||
|
||||
class SpinBox : public QSpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SpinBox(QWidget* parent = 0);
|
||||
|
||||
signals:
|
||||
void returnPressed();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(SpinBox)
|
||||
|
||||
};
|
||||
|
||||
// mapping spin box
|
||||
|
||||
class MappingSpinBox : public SpinBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct TextValueMapper
|
||||
{
|
||||
virtual ~TextValueMapper() {}
|
||||
|
||||
virtual QString textFromValue(int val, bool& ok) const = 0;
|
||||
virtual int valueFromText(const QString& text, bool& ok) const = 0;
|
||||
};
|
||||
|
||||
MappingSpinBox(TextValueMapper* mapper, QWidget* parent = 0);
|
||||
|
||||
protected:
|
||||
QString textFromValue(int val) const;
|
||||
int valueFromText(const QString& text) const;
|
||||
|
||||
QValidator::State validate(QString& input, int& pos) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(MappingSpinBox)
|
||||
|
||||
QScopedPointer< TextValueMapper > m_mapper;
|
||||
|
||||
};
|
||||
|
||||
int getMappedNumber(MappingSpinBox::TextValueMapper* mapper,
|
||||
QWidget* parent, const QString& title, const QString& caption,
|
||||
int value = 0, int min = -2147483647, int max = 2147483647,
|
||||
bool* ok = 0, Qt::WindowFlags flags = 0);
|
||||
|
||||
// progress line edit
|
||||
|
||||
class ProgressLineEdit : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProgressLineEdit(QWidget* parent = 0);
|
||||
|
||||
int progress() const;
|
||||
void setProgress(int progress);
|
||||
|
||||
signals:
|
||||
void returnPressed(Qt::KeyboardModifiers modifiers);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event);
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ProgressLineEdit)
|
||||
|
||||
int m_progress;
|
||||
|
||||
};
|
||||
|
||||
// search line edit
|
||||
|
||||
class SearchLineEdit : public ProgressLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SearchLineEdit(QWidget* parent = 0);
|
||||
|
||||
public slots:
|
||||
void startSearch();
|
||||
|
||||
void startTimer();
|
||||
void stopTimer();
|
||||
|
||||
signals:
|
||||
void searchInitiated(const QString& text, bool modified = false);
|
||||
|
||||
protected slots:
|
||||
void on_timeout();
|
||||
void on_returnPressed(Qt::KeyboardModifiers modifiers);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(SearchLineEdit)
|
||||
|
||||
QTimer* m_timer;
|
||||
|
||||
};
|
||||
|
||||
// splitter
|
||||
|
||||
class Splitter : public QSplitter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Splitter(Qt::Orientation orientation, QWidget* parent = 0);
|
||||
|
||||
QWidget* currentWidget() const;
|
||||
void setCurrentWidget(QWidget* const currentWidget);
|
||||
|
||||
void setUniformSizes();
|
||||
|
||||
signals:
|
||||
void currentWidgetChanged(QWidget* currentWidget);
|
||||
|
||||
protected slots:
|
||||
void on_focusChanged(QWidget* old, QWidget* now);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Splitter)
|
||||
|
||||
int m_currentIndex;
|
||||
|
||||
};
|
||||
|
||||
// fallback icons
|
||||
|
||||
inline QIcon loadIconWithFallback(const QString& name)
|
||||
{
|
||||
QIcon icon = QIcon::fromTheme(name);
|
||||
|
||||
if(icon.isNull())
|
||||
{
|
||||
icon = QIcon(QLatin1String(":icons/") + name);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
void openInNewWindow(const QString& filePath, int page);
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // MISCELLANEOUS_H
|
218
sources/model.h
Parasts fails
218
sources/model.h
Parasts fails
@ -0,0 +1,218 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2013-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DOCUMENTMODEL_H
|
||||
#define DOCUMENTMODEL_H
|
||||
|
||||
#include <QList>
|
||||
#include <QtPlugin>
|
||||
#include <QWidget>
|
||||
#include <QVector>
|
||||
|
||||
class QAbstractItemModel;
|
||||
class QColor;
|
||||
class QImage;
|
||||
class QPrinter;
|
||||
class QSizeF;
|
||||
|
||||
#include "global.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
struct Link
|
||||
{
|
||||
QPainterPath boundary;
|
||||
|
||||
int page;
|
||||
qreal left;
|
||||
qreal top;
|
||||
|
||||
QString urlOrFileName;
|
||||
|
||||
Link() : boundary(), page(-1), left(qQNaN()), top(qQNaN()), urlOrFileName() {}
|
||||
|
||||
Link(const QPainterPath& boundary, int page, qreal left = qQNaN(), qreal top = qQNaN()) : boundary(boundary), page(page), left(left), top(top), urlOrFileName() {}
|
||||
Link(const QRectF& boundingRect, int page, qreal left = qQNaN(), qreal top = qQNaN()) : boundary(), page(page), left(left), top(top), urlOrFileName() { boundary.addRect(boundingRect); }
|
||||
|
||||
Link(const QPainterPath& boundary, const QString& url) : boundary(boundary), page(-1), left(qQNaN()), top(qQNaN()), urlOrFileName(url) {}
|
||||
Link(const QRectF& boundingRect, const QString& url) : boundary(), page(-1), left(qQNaN()), top(qQNaN()), urlOrFileName(url) { boundary.addRect(boundingRect); }
|
||||
|
||||
Link(const QPainterPath& boundary, const QString& fileName, int page) : boundary(boundary), page(page), left(qQNaN()), top(qQNaN()), urlOrFileName(fileName) {}
|
||||
Link(const QRectF& boundingRect, const QString& fileName, int page) : boundary(), page(page), left(qQNaN()), top(qQNaN()), urlOrFileName(fileName) { boundary.addRect(boundingRect); }
|
||||
|
||||
};
|
||||
|
||||
struct Section;
|
||||
|
||||
typedef QVector< Section > Outline;
|
||||
|
||||
struct Section
|
||||
{
|
||||
QString title;
|
||||
Link link;
|
||||
|
||||
Outline children;
|
||||
|
||||
};
|
||||
|
||||
typedef QVector< QPair< QString, QString > > Properties;
|
||||
|
||||
class Annotation : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Annotation(QObject* parent = 0) : QObject(parent) {}
|
||||
virtual ~Annotation() {}
|
||||
|
||||
virtual QRectF boundary() const = 0;
|
||||
virtual QString contents() const = 0;
|
||||
|
||||
virtual QWidget* createWidget() = 0;
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
};
|
||||
|
||||
class FormField : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FormField(QObject* parent = 0) : QObject(parent) {}
|
||||
virtual ~FormField() {}
|
||||
|
||||
virtual QRectF boundary() const = 0;
|
||||
virtual QString name() const = 0;
|
||||
|
||||
virtual QWidget* createWidget() = 0;
|
||||
|
||||
signals:
|
||||
void wasModified();
|
||||
|
||||
};
|
||||
|
||||
class Page
|
||||
{
|
||||
public:
|
||||
virtual ~Page() {}
|
||||
|
||||
virtual QSizeF size() const = 0;
|
||||
|
||||
virtual QImage render(qreal horizontalResolution = 72.0, qreal verticalResolution = 72.0, Rotation rotation = RotateBy0, QRect boundingRect = QRect()) const = 0;
|
||||
|
||||
virtual QString label() const { return QString(); }
|
||||
|
||||
virtual QList< Link* > links() const { return QList< Link* >(); }
|
||||
|
||||
virtual QString text(const QRectF& rect) const { Q_UNUSED(rect); return QString(); }
|
||||
virtual QString cachedText(const QRectF& rect) const { return text(rect); }
|
||||
|
||||
virtual QList< QRectF > search(const QString& text, bool matchCase, bool wholeWords) const { Q_UNUSED(text); Q_UNUSED(matchCase); Q_UNUSED(wholeWords); return QList< QRectF >(); }
|
||||
|
||||
virtual QList< Annotation* > annotations() const { return QList< Annotation* >(); }
|
||||
|
||||
virtual bool canAddAndRemoveAnnotations() const { return false; }
|
||||
virtual Annotation* addTextAnnotation(const QRectF& boundary, const QColor& color) { Q_UNUSED(boundary); Q_UNUSED(color); return 0; }
|
||||
virtual Annotation* addHighlightAnnotation(const QRectF& boundary, const QColor& color) { Q_UNUSED(boundary); Q_UNUSED(color); return 0; }
|
||||
virtual void removeAnnotation(Annotation* annotation) { Q_UNUSED(annotation); }
|
||||
|
||||
virtual QList< FormField* > formFields() const { return QList< FormField* >(); }
|
||||
|
||||
};
|
||||
|
||||
class Document
|
||||
{
|
||||
public:
|
||||
virtual ~Document() {}
|
||||
|
||||
virtual int numberOfPages() const = 0;
|
||||
|
||||
virtual Page* page(int index) const = 0;
|
||||
|
||||
virtual bool isLocked() const { return false; }
|
||||
virtual bool unlock(const QString& password) { Q_UNUSED(password); return false; }
|
||||
|
||||
virtual QStringList saveFilter() const { return QStringList(); }
|
||||
|
||||
virtual bool canSave() const { return false; }
|
||||
virtual bool save(const QString& filePath, bool withChanges) const { Q_UNUSED(filePath); Q_UNUSED(withChanges); return false; }
|
||||
|
||||
virtual bool canBePrintedUsingCUPS() const { return false; }
|
||||
|
||||
virtual void setPaperColor(const QColor& paperColor) { Q_UNUSED(paperColor); }
|
||||
|
||||
enum
|
||||
{
|
||||
PageRole = Qt::UserRole + 1,
|
||||
LeftRole,
|
||||
TopRole,
|
||||
FileNameRole,
|
||||
ExpansionRole
|
||||
};
|
||||
|
||||
virtual Outline outline() const { return Outline(); }
|
||||
virtual Properties properties() const { return Properties(); }
|
||||
|
||||
virtual QAbstractItemModel* fonts() const { return 0; }
|
||||
|
||||
virtual bool wantsContinuousMode() const { return false; }
|
||||
virtual bool wantsSinglePageMode() const { return false; }
|
||||
virtual bool wantsTwoPagesMode() const { return false; }
|
||||
virtual bool wantsTwoPagesWithCoverPageMode() const { return false; }
|
||||
virtual bool wantsRightToLeftMode() const { return false; }
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class SettingsWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsWidget(QWidget* parent = 0) : QWidget(parent) {}
|
||||
|
||||
virtual void accept() = 0;
|
||||
virtual void reset() = 0;
|
||||
|
||||
};
|
||||
|
||||
class Plugin
|
||||
{
|
||||
public:
|
||||
virtual ~Plugin() {}
|
||||
|
||||
virtual Model::Document* loadDocument(const QString& filePath) const = 0;
|
||||
|
||||
virtual SettingsWidget* createSettingsWidget(QWidget* parent = 0) const { Q_UNUSED(parent); return 0; }
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
Q_DECLARE_INTERFACE(qpdfview::Plugin, "local.qpdfview.Plugin")
|
||||
|
||||
#endif // DOCUMENTMODEL_H
|
1321
sources/pageitem.cpp
Parasts fails
1321
sources/pageitem.cpp
Parasts fails
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
228
sources/pageitem.h
Parasts fails
228
sources/pageitem.h
Parasts fails
@ -0,0 +1,228 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PAGEITEM_H
|
||||
#define PAGEITEM_H
|
||||
|
||||
#include <QCache>
|
||||
#include <QFutureWatcher>
|
||||
#include <QGraphicsObject>
|
||||
#include <QIcon>
|
||||
#include <QSet>
|
||||
|
||||
class QGraphicsProxyWidget;
|
||||
|
||||
#include "renderparam.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
struct Link;
|
||||
class Annotation;
|
||||
class FormField;
|
||||
class Page;
|
||||
}
|
||||
|
||||
class Settings;
|
||||
class RenderTask;
|
||||
class TileItem;
|
||||
|
||||
class PageItem : public QGraphicsObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class TileItem;
|
||||
|
||||
public:
|
||||
enum PaintMode
|
||||
{
|
||||
DefaultMode,
|
||||
PresentationMode,
|
||||
ThumbnailMode
|
||||
};
|
||||
|
||||
PageItem(Model::Page* page, int index, PaintMode paintMode = DefaultMode, QGraphicsItem* parent = 0);
|
||||
~PageItem();
|
||||
|
||||
const QRectF& uncroppedBoundingRect() const { return m_boundingRect; }
|
||||
|
||||
QRectF boundingRect() const;
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*);
|
||||
|
||||
int index() const { return m_index; }
|
||||
|
||||
const QSizeF& size() const { return m_size; }
|
||||
|
||||
QSizeF displayedSize() const { return displayedSize(renderParam()); }
|
||||
QSizeF displayedSize(const RenderParam& renderParam) const;
|
||||
|
||||
const QList< QRectF >& highlights() const { return m_highlights; }
|
||||
void setHighlights(const QList< QRectF >& highlights);
|
||||
|
||||
RubberBandMode rubberBandMode() const { return m_rubberBandMode; }
|
||||
void setRubberBandMode(RubberBandMode rubberBandMode);
|
||||
|
||||
bool showsAnnotationOverlay() const { return !m_annotationOverlay.isEmpty(); }
|
||||
bool showsFormFieldOverlay() const { return !m_formFieldOverlay.isEmpty(); }
|
||||
|
||||
const RenderParam& renderParam() const { return m_renderParam; }
|
||||
void setRenderParam(const RenderParam& renderParam);
|
||||
|
||||
const QTransform& transform() const { return m_transform; }
|
||||
const QTransform& normalizedTransform() const { return m_normalizedTransform; }
|
||||
|
||||
QPointF sourcePos(QPointF point) const { return m_transform.inverted().map(point); }
|
||||
QPointF normalizedSourcePos(QPointF point) const { return m_normalizedTransform.inverted().map(point); }
|
||||
|
||||
signals:
|
||||
void cropRectChanged();
|
||||
|
||||
void linkClicked(bool newTab, int page, qreal left = qQNaN(), qreal top = qQNaN());
|
||||
void linkClicked(bool newTab, const QString& fileName, int page);
|
||||
void linkClicked(const QString& url);
|
||||
|
||||
void rubberBandStarted();
|
||||
void rubberBandFinished();
|
||||
|
||||
void zoomToSelection(int page, const QRectF& rect);
|
||||
void openInSourceEditor(int page, QPointF pos);
|
||||
|
||||
void wasModified();
|
||||
|
||||
public slots:
|
||||
void refresh(bool keepObsoletePixmaps = false, bool dropCachedPixmaps = false);
|
||||
|
||||
int startRender(bool prefetch = false);
|
||||
void cancelRender();
|
||||
|
||||
protected slots:
|
||||
void showAnnotationOverlay(Model::Annotation* selectedAnnotation);
|
||||
void hideAnnotationOverlay(bool deleteLater = true);
|
||||
void updateAnnotationOverlay();
|
||||
|
||||
void showFormFieldOverlay(Model::FormField* selectedFormField);
|
||||
void hideFormFieldOverlay(bool deleteLater = true);
|
||||
void updateFormFieldOverlay();
|
||||
|
||||
protected:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent* event);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent* event);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
|
||||
|
||||
void contextMenuEvent(QGraphicsSceneContextMenuEvent* event);
|
||||
|
||||
private slots:
|
||||
void on_loadInteractiveElements_finished();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PageItem)
|
||||
|
||||
static Settings* s_settings;
|
||||
|
||||
Model::Page* m_page;
|
||||
QSizeF m_size;
|
||||
|
||||
QRectF m_cropRect;
|
||||
|
||||
void updateCropRect();
|
||||
|
||||
int m_index;
|
||||
PaintMode m_paintMode;
|
||||
|
||||
bool presentationMode() const;
|
||||
bool thumbnailMode() const;
|
||||
|
||||
bool useTiling() const;
|
||||
|
||||
QList< QRectF > m_highlights;
|
||||
|
||||
// interactive elements
|
||||
|
||||
QFutureWatcher< void >* m_loadInteractiveElements;
|
||||
|
||||
void startLoadInteractiveElements();
|
||||
void loadInteractiveElements();
|
||||
|
||||
QList< Model::Link* > m_links;
|
||||
QList< Model::Annotation* > m_annotations;
|
||||
QList< Model::FormField* > m_formFields;
|
||||
|
||||
RubberBandMode m_rubberBandMode;
|
||||
QRectF m_rubberBand;
|
||||
|
||||
void copyToClipboard(QPoint screenPos);
|
||||
void addAnnotation(QPoint screenPos);
|
||||
|
||||
void showLinkContextMenu(Model::Link* link, QPoint screenPos);
|
||||
void showAnnotationContextMenu(Model::Annotation* annotation, QPoint screenPos);
|
||||
|
||||
// overlay
|
||||
|
||||
typedef QMap< Model::Annotation*, QGraphicsProxyWidget* > AnnotationOverlay;
|
||||
AnnotationOverlay m_annotationOverlay;
|
||||
|
||||
typedef QMap< Model::FormField*, QGraphicsProxyWidget* > FormFieldOverlay;
|
||||
FormFieldOverlay m_formFieldOverlay;
|
||||
|
||||
template< typename Overlay, typename Element > void showOverlay(Overlay& overlay, const char* hideOverlay, const QList< Element* >& elements, Element* selectedElement);
|
||||
template< typename Overlay, typename Element > void addProxy(Overlay& overlay, const char* hideOverlay, Element* element);
|
||||
template< typename Overlay > void hideOverlay(Overlay& overlay, bool deleteLater);
|
||||
template< typename Overlay > void updateOverlay(const Overlay& overlay) const;
|
||||
|
||||
void setProxyGeometry(Model::Annotation* annotation, QGraphicsProxyWidget* proxy) const;
|
||||
void setProxyGeometry(Model::FormField* formField, QGraphicsProxyWidget* proxy) const;
|
||||
|
||||
// geometry
|
||||
|
||||
RenderParam m_renderParam;
|
||||
|
||||
QTransform m_transform;
|
||||
QTransform m_normalizedTransform;
|
||||
QRectF m_boundingRect;
|
||||
|
||||
void prepareGeometry();
|
||||
|
||||
QVector< TileItem* > m_tileItems;
|
||||
mutable QSet< TileItem* > m_exposedTileItems;
|
||||
|
||||
void prepareTiling();
|
||||
|
||||
// paint
|
||||
|
||||
void paintPage(QPainter* painter, const QRectF& exposedRect) const;
|
||||
|
||||
void paintLinks(QPainter* painter) const;
|
||||
void paintFormFields(QPainter* painter) const;
|
||||
|
||||
void paintHighlights(QPainter* painter) const;
|
||||
void paintRubberBand(QPainter* painter) const;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // PAGEITEM_H
|
1333
sources/pdfmodel.cpp
Parasts fails
1333
sources/pdfmodel.cpp
Parasts fails
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
267
sources/pdfmodel.h
Parasts fails
267
sources/pdfmodel.h
Parasts fails
@ -0,0 +1,267 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2013-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PDFMODEL_H
|
||||
#define PDFMODEL_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMutex>
|
||||
#include <QScopedPointer>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QFormLayout;
|
||||
class QSettings;
|
||||
|
||||
namespace Poppler
|
||||
{
|
||||
class Annotation;
|
||||
class Document;
|
||||
class FormField;
|
||||
class Page;
|
||||
}
|
||||
|
||||
#include "model.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class PdfPlugin;
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class PdfAnnotation : public Annotation
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class PdfPage;
|
||||
|
||||
public:
|
||||
~PdfAnnotation();
|
||||
|
||||
QRectF boundary() const;
|
||||
QString contents() const;
|
||||
|
||||
QWidget* createWidget();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PdfAnnotation)
|
||||
|
||||
PdfAnnotation(QMutex* mutex, Poppler::Annotation* annotation);
|
||||
|
||||
mutable QMutex* m_mutex;
|
||||
Poppler::Annotation* m_annotation;
|
||||
|
||||
};
|
||||
|
||||
class PdfFormField : public FormField
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class PdfPage;
|
||||
|
||||
public:
|
||||
~PdfFormField();
|
||||
|
||||
QRectF boundary() const;
|
||||
QString name() const;
|
||||
|
||||
QWidget* createWidget();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PdfFormField)
|
||||
|
||||
PdfFormField(QMutex* mutex, Poppler::FormField* formField);
|
||||
|
||||
mutable QMutex* m_mutex;
|
||||
Poppler::FormField* m_formField;
|
||||
|
||||
};
|
||||
|
||||
class PdfPage : public Page
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Model::PdfPage)
|
||||
|
||||
friend class PdfDocument;
|
||||
|
||||
public:
|
||||
~PdfPage();
|
||||
|
||||
QSizeF size() const;
|
||||
|
||||
QImage render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const;
|
||||
|
||||
QString label() const;
|
||||
|
||||
QList< Link* > links() const;
|
||||
|
||||
QString text(const QRectF& rect) const;
|
||||
QString cachedText(const QRectF& rect) const;
|
||||
|
||||
QList< QRectF > search(const QString& text, bool matchCase, bool wholeWords) const;
|
||||
|
||||
QList< Annotation* > annotations() const;
|
||||
|
||||
bool canAddAndRemoveAnnotations() const;
|
||||
Annotation* addTextAnnotation(const QRectF& boundary, const QColor& color);
|
||||
Annotation* addHighlightAnnotation(const QRectF& boundary, const QColor& color);
|
||||
void removeAnnotation(Annotation* annotation);
|
||||
|
||||
QList< FormField* > formFields() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PdfPage)
|
||||
|
||||
PdfPage(QMutex* mutex, Poppler::Page* page);
|
||||
|
||||
mutable QMutex* m_mutex;
|
||||
Poppler::Page* m_page;
|
||||
|
||||
};
|
||||
|
||||
class PdfDocument : public Document
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Model::PdfDocument)
|
||||
|
||||
friend class qpdfview::PdfPlugin;
|
||||
|
||||
public:
|
||||
~PdfDocument();
|
||||
|
||||
int numberOfPages() const;
|
||||
|
||||
Page* page(int index) const;
|
||||
|
||||
bool isLocked() const;
|
||||
bool unlock(const QString& password);
|
||||
|
||||
QStringList saveFilter() const;
|
||||
|
||||
bool canSave() const;
|
||||
bool save(const QString& filePath, bool withChanges) const;
|
||||
|
||||
bool canBePrintedUsingCUPS() const;
|
||||
|
||||
void setPaperColor(const QColor& paperColor);
|
||||
|
||||
Outline outline() const;
|
||||
Properties properties() const;
|
||||
|
||||
QAbstractItemModel* fonts() const;
|
||||
|
||||
bool wantsContinuousMode() const;
|
||||
bool wantsSinglePageMode() const;
|
||||
bool wantsTwoPagesMode() const;
|
||||
bool wantsTwoPagesWithCoverPageMode() const;
|
||||
bool wantsRightToLeftMode() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PdfDocument)
|
||||
|
||||
PdfDocument(Poppler::Document* document);
|
||||
|
||||
mutable QMutex m_mutex;
|
||||
Poppler::Document* m_document;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class PdfSettingsWidget : public SettingsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PdfSettingsWidget(QSettings* settings, QWidget* parent = 0);
|
||||
|
||||
void accept();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PdfSettingsWidget)
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
QFormLayout* m_layout;
|
||||
|
||||
QCheckBox* m_antialiasingCheckBox;
|
||||
QCheckBox* m_textAntialiasingCheckBox;
|
||||
|
||||
#ifdef HAS_POPPLER_18
|
||||
|
||||
QComboBox* m_textHintingComboBox;
|
||||
|
||||
#else
|
||||
|
||||
QCheckBox* m_textHintingCheckBox;
|
||||
|
||||
#endif // HAS_POPPLER_18
|
||||
|
||||
#ifdef HAS_POPPLER_35
|
||||
|
||||
QCheckBox* m_ignorePaperColorCheckBox;
|
||||
|
||||
#endif // HAS_POPPLER_35
|
||||
|
||||
#ifdef HAS_POPPLER_22
|
||||
|
||||
QCheckBox* m_overprintPreviewCheckBox;
|
||||
|
||||
#endif // HAS_POPPLER_22
|
||||
|
||||
#ifdef HAS_POPPLER_24
|
||||
|
||||
QComboBox* m_thinLineModeComboBox;
|
||||
|
||||
#endif // HAS_POPPLER_24
|
||||
|
||||
QComboBox* m_backendComboBox;
|
||||
|
||||
};
|
||||
|
||||
class PdfPlugin : public QObject, Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(qpdfview::Plugin)
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
Q_PLUGIN_METADATA(IID "local.qpdfview.Plugin")
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
public:
|
||||
PdfPlugin(QObject* parent = 0);
|
||||
|
||||
Model::Document* loadDocument(const QString& filePath) const;
|
||||
|
||||
SettingsWidget* createSettingsWidget(QWidget* parent) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PdfPlugin)
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // PDFMODEL_H
|
640
sources/pluginhandler.cpp
Parasts fails
640
sources/pluginhandler.cpp
Parasts fails
@ -0,0 +1,640 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 S. Razi Alavizadeh
|
||||
Copyright 2012-2013, 2015-2018 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "pluginhandler.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QImageReader>
|
||||
#include <QMessageBox>
|
||||
#include <QPluginLoader>
|
||||
#include <QProcess>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
#include <QMimeDatabase>
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
#ifdef WITH_MAGIC
|
||||
|
||||
#include <magic.h>
|
||||
|
||||
#endif // WITH_MAGIC
|
||||
|
||||
#include "model.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace qpdfview;
|
||||
|
||||
Plugin* loadStaticPlugin(const QString& objectName)
|
||||
{
|
||||
foreach(QObject* object, QPluginLoader::staticInstances())
|
||||
{
|
||||
if(object->objectName() == objectName)
|
||||
{
|
||||
if(Plugin* plugin = qobject_cast< Plugin* >(object))
|
||||
{
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qCritical() << "Could not load static plug-in:" << objectName;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Plugin* loadPlugin(const QString& fileName)
|
||||
{
|
||||
QPluginLoader pluginLoader;
|
||||
|
||||
#ifdef PLUGIN_RESOLVE_ALL
|
||||
|
||||
pluginLoader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
||||
|
||||
#endif // PLUGIN_RESOLVE_ALL
|
||||
|
||||
const QString localFileName = QDir(QApplication::applicationDirPath()).absoluteFilePath(fileName);
|
||||
pluginLoader.setFileName(localFileName);
|
||||
|
||||
if(!pluginLoader.load())
|
||||
{
|
||||
const QString localErrorString = pluginLoader.errorString();
|
||||
|
||||
const QString globalFileName = QDir(PLUGIN_INSTALL_PATH).absoluteFilePath(fileName);
|
||||
pluginLoader.setFileName(globalFileName);
|
||||
|
||||
if(!pluginLoader.load())
|
||||
{
|
||||
const QString globalErrorString = pluginLoader.errorString();
|
||||
|
||||
qCritical() << "Could not load local plug-in:" << localFileName;
|
||||
qCritical() << localErrorString;
|
||||
|
||||
qCritical() << "Could not load global plug-in:" << globalFileName;
|
||||
qCritical() << globalErrorString;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Plugin* plugin = qobject_cast< Plugin* >(pluginLoader.instance());
|
||||
|
||||
if(plugin == 0)
|
||||
{
|
||||
qCritical() << "Could not instantiate plug-in:" << pluginLoader.fileName();
|
||||
qCritical() << pluginLoader.errorString();
|
||||
}
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
QStringList supportedImageFormats()
|
||||
{
|
||||
QStringList formats;
|
||||
|
||||
foreach(const QByteArray& format, QImageReader::supportedImageFormats())
|
||||
{
|
||||
const QString name = QString::fromLocal8Bit(format);
|
||||
|
||||
formats.append(QLatin1String("*.") + name.toLower());
|
||||
formats.append(QLatin1String("*.") + name.toUpper());
|
||||
}
|
||||
|
||||
return formats;
|
||||
}
|
||||
|
||||
struct MimeTypeMapping
|
||||
{
|
||||
const char* mimeType;
|
||||
PluginHandler::FileType fileType;
|
||||
const char* suffix;
|
||||
const char* alternativeSuffix;
|
||||
};
|
||||
|
||||
const MimeTypeMapping mimeTypeMappings[] =
|
||||
{
|
||||
{ "application/pdf", PluginHandler::PDF, "pdf", 0 },
|
||||
{ "application/postscript", PluginHandler::PS, "ps", "eps" },
|
||||
{ "image/vnd.djvu", PluginHandler::DjVu, "djvu", "djv" },
|
||||
{ "application/x-gzip", PluginHandler::GZip, "gz", 0 },
|
||||
{ "application/x-bzip2", PluginHandler::BZip2, "bz2", 0 },
|
||||
{ "application/x-xz", PluginHandler::XZ, "xz", 0 },
|
||||
{ "application/epub+zip", PluginHandler::EPUB, "epub", 0 },
|
||||
{ "application/x-fictionbook+xml", PluginHandler::FB2, "fb2", 0 },
|
||||
{ "application/x-zip-compressed-fb2", PluginHandler::FB2, "fb2", 0 },
|
||||
{ "application/zip", PluginHandler::ZIP, "zip", 0 }
|
||||
};
|
||||
|
||||
const MimeTypeMapping* const endOfMimeTypeMappings = mimeTypeMappings + sizeof(mimeTypeMappings) / sizeof(mimeTypeMappings[0]);
|
||||
|
||||
void matchArchiveAndImageType(const QString& filePath, PluginHandler::FileType& fileType)
|
||||
{
|
||||
if(fileType == PluginHandler::ZIP)
|
||||
{
|
||||
const QString suffix = QFileInfo(filePath).suffix().toLower();
|
||||
|
||||
if (suffix == "cbz")
|
||||
{
|
||||
fileType = PluginHandler::CBZ;
|
||||
}
|
||||
else if (suffix == "xps" || suffix == "oxps")
|
||||
{
|
||||
fileType = PluginHandler::XPS;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileType = PluginHandler::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
if(fileType == PluginHandler::Unknown && !QImageReader::imageFormat(filePath).isEmpty())
|
||||
{
|
||||
fileType = PluginHandler::Image;
|
||||
}
|
||||
}
|
||||
|
||||
PluginHandler::FileType matchFileType(const QString& filePath)
|
||||
{
|
||||
PluginHandler::FileType fileType = PluginHandler::Unknown;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
const QMimeType mimeType = QMimeDatabase().mimeTypeForFile(filePath, QMimeDatabase::MatchContent);
|
||||
|
||||
for(const MimeTypeMapping* mapping = mimeTypeMappings; mapping != endOfMimeTypeMappings; ++mapping)
|
||||
{
|
||||
if(mimeType.inherits(mapping->mimeType))
|
||||
{
|
||||
fileType = mapping->fileType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
matchArchiveAndImageType(filePath, fileType);
|
||||
|
||||
if(fileType == PluginHandler::Unknown)
|
||||
{
|
||||
qDebug() << "Unknown MIME type:" << mimeType.name();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef WITH_MAGIC
|
||||
|
||||
magic_t cookie = magic_open(MAGIC_MIME_TYPE | MAGIC_SYMLINK);
|
||||
|
||||
if(magic_load(cookie, 0) == 0)
|
||||
{
|
||||
const char* const mimeType = magic_file(cookie, QFile::encodeName(filePath));
|
||||
|
||||
for(const MimeTypeMapping* mapping = mimeTypeMappings; mapping != endOfMimeTypeMappings; ++mapping)
|
||||
{
|
||||
if(qstrcmp(mimeType, mapping->mimeType) == 0)
|
||||
{
|
||||
fileType = mapping->fileType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
matchArchiveAndImageType(filePath, fileType);
|
||||
|
||||
if(fileType == PluginHandler::Unknown)
|
||||
{
|
||||
qDebug() << "Unknown MIME type:" << mimeType;
|
||||
}
|
||||
}
|
||||
|
||||
magic_close(cookie);
|
||||
|
||||
#else
|
||||
|
||||
const QString suffix = QFileInfo(filePath).suffix().toLower();
|
||||
|
||||
for(const MimeTypeMapping* mapping = mimeTypeMappings; mapping != endOfMimeTypeMappings; ++mapping)
|
||||
{
|
||||
if(suffix == mapping->suffix || (mapping->alternativeSuffix != 0 && suffix == mapping->alternativeSuffix))
|
||||
{
|
||||
fileType = mapping->fileType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
matchArchiveAndImageType(filePath, fileType);
|
||||
|
||||
if(fileType == PluginHandler::Unknown)
|
||||
{
|
||||
qDebug() << "Unkown file suffix:" << suffix;
|
||||
}
|
||||
|
||||
#endif // WITH_MAGIC
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
return fileType;
|
||||
}
|
||||
|
||||
int execute(QProcess& process, const QString& program, const QStringList& arguments = QStringList())
|
||||
{
|
||||
process.start(program, arguments, QIODevice::NotOpen);
|
||||
|
||||
if(!process.waitForStarted())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!process.waitForFinished())
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
return process.exitCode();
|
||||
}
|
||||
|
||||
QStringList supportedCompressedFormats()
|
||||
{
|
||||
QStringList formats;
|
||||
|
||||
QProcess process;
|
||||
process.setStandardInputFile("/dev/null");
|
||||
process.setStandardOutputFile("/dev/null");
|
||||
|
||||
if(execute(process, "gzip") >= 0)
|
||||
{
|
||||
formats.append("*.gz *.GZ");
|
||||
}
|
||||
|
||||
if(execute(process, "bzip2") >= 0)
|
||||
{
|
||||
formats.append("*.bz2 *.BZ2");
|
||||
}
|
||||
|
||||
if(execute(process, "xz") >= 0)
|
||||
{
|
||||
formats.append("*.xz *.XZ");
|
||||
}
|
||||
|
||||
return formats;
|
||||
}
|
||||
|
||||
QString decompressToTemporaryFile(const QString& filePath, const PluginHandler::FileType fileType)
|
||||
{
|
||||
const char* command;
|
||||
|
||||
switch(fileType)
|
||||
{
|
||||
case PluginHandler::GZip:
|
||||
command = "gzip";
|
||||
break;
|
||||
case PluginHandler::BZip2:
|
||||
command = "bzip2";
|
||||
break;
|
||||
case PluginHandler::XZ:
|
||||
command = "xz";
|
||||
break;
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
|
||||
QTemporaryFile file;
|
||||
file.setAutoRemove(false);
|
||||
|
||||
if(!file.open())
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
QProcess process;
|
||||
process.setStandardInputFile("/dev/null");
|
||||
process.setStandardOutputFile(file.fileName());
|
||||
|
||||
if(execute(process, command, QStringList() << "-dck" << filePath) != 0)
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
return file.fileName();
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
PluginHandler* PluginHandler::s_instance = 0;
|
||||
|
||||
PluginHandler* PluginHandler::instance()
|
||||
{
|
||||
if(s_instance == 0)
|
||||
{
|
||||
s_instance = new PluginHandler(qApp);
|
||||
}
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
PluginHandler::~PluginHandler()
|
||||
{
|
||||
s_instance = 0;
|
||||
}
|
||||
|
||||
QLatin1String PluginHandler::fileTypeName(PluginHandler::FileType fileType)
|
||||
{
|
||||
switch(fileType)
|
||||
{
|
||||
default:
|
||||
case PluginHandler::Unknown:
|
||||
return QLatin1String("Unknown");
|
||||
case PluginHandler::PDF:
|
||||
return QLatin1String("PDF");
|
||||
case PluginHandler::PS:
|
||||
return QLatin1String("PS");
|
||||
case PluginHandler::DjVu:
|
||||
return QLatin1String("DjVu");
|
||||
case PluginHandler::Image:
|
||||
return QLatin1String("Image");
|
||||
case PluginHandler::EPUB:
|
||||
return QLatin1String("EPUB");
|
||||
case PluginHandler::XPS:
|
||||
return QLatin1String("XPS");
|
||||
case PluginHandler::FB2:
|
||||
return QLatin1String("FictionBook2");
|
||||
case PluginHandler::CBZ:
|
||||
return QLatin1String("CBZ");
|
||||
case PluginHandler::GZip:
|
||||
case PluginHandler::BZip2:
|
||||
case PluginHandler::XZ:
|
||||
case PluginHandler::ZIP:
|
||||
return QLatin1String("Compressed");
|
||||
}
|
||||
}
|
||||
|
||||
QStringList PluginHandler::openFilter()
|
||||
{
|
||||
QStringList openFilter;
|
||||
QStringList supportedFormats;
|
||||
|
||||
#if defined(WITH_PDF) || defined(WITH_FITZ)
|
||||
|
||||
openFilter.append(QLatin1String("Portable document format (*.pdf *.PDF)"));
|
||||
supportedFormats.append(QLatin1String("*.pdf *.PDF"));
|
||||
|
||||
#endif // WITH_PDF // WITH_FITZ
|
||||
|
||||
#if defined(WITH_FITZ)
|
||||
|
||||
openFilter.append(QLatin1String("EPUB (*.epub *.EPUB)"));
|
||||
supportedFormats.append(QLatin1String("*.epub *.EPUB"));
|
||||
|
||||
openFilter.append(QLatin1String("XPS (*.xps *.XPS *.oxps *.OXPS)"));
|
||||
supportedFormats.append(QLatin1String("*.xps *.XPS *.oxps *.OXPS"));
|
||||
|
||||
openFilter.append(QLatin1String("FictionBook 2 (*.fb2 *.FB2)"));
|
||||
supportedFormats.append(QLatin1String("*.fb2 *.FB2"));
|
||||
|
||||
openFilter.append(QLatin1String("CBZ (*.cbz *.CBZ)"));
|
||||
supportedFormats.append(QLatin1String("*.cbz *.CBZ"));
|
||||
|
||||
#endif // WITH_FITZ
|
||||
|
||||
#ifdef WITH_PS
|
||||
|
||||
openFilter.append(QLatin1String("PostScript (*.ps *.PS)"));
|
||||
openFilter.append(QLatin1String("Encapsulated PostScript (*.eps *.EPS)"));
|
||||
supportedFormats.append(QLatin1String("*.ps *.PS *.eps *.EPS"));
|
||||
|
||||
#endif // WITH_PS
|
||||
|
||||
#ifdef WITH_DJVU
|
||||
|
||||
openFilter.append(QLatin1String("DjVu (*.djvu *.DJVU *.djv *.DJV)"));
|
||||
supportedFormats.append(QLatin1String("*.djvu *.DJVU *.djv *.DJV"));
|
||||
|
||||
#endif // WITH_DJVU
|
||||
|
||||
#ifdef WITH_IMAGE
|
||||
|
||||
static QStringList imageFormats;
|
||||
|
||||
if(imageFormats.isEmpty())
|
||||
{
|
||||
imageFormats = supportedImageFormats();
|
||||
}
|
||||
|
||||
if(!imageFormats.isEmpty())
|
||||
{
|
||||
openFilter.append(tr("Image (%1)").arg(imageFormats.join(QLatin1String(" "))));
|
||||
supportedFormats.append(imageFormats);
|
||||
}
|
||||
|
||||
#endif // WITH_IMAGE
|
||||
|
||||
static QStringList compressedFormats;
|
||||
|
||||
if(compressedFormats.isEmpty())
|
||||
{
|
||||
compressedFormats = supportedCompressedFormats();
|
||||
}
|
||||
|
||||
if(!compressedFormats.isEmpty())
|
||||
{
|
||||
openFilter.append(tr("Compressed (%1)").arg(compressedFormats.join(QLatin1String(" "))));
|
||||
supportedFormats.append(compressedFormats);
|
||||
}
|
||||
|
||||
openFilter.prepend(tr("Supported formats (%1)").arg(supportedFormats.join(QLatin1String(" "))));
|
||||
|
||||
return openFilter;
|
||||
}
|
||||
|
||||
Model::Document* PluginHandler::loadDocument(const QString& filePath)
|
||||
{
|
||||
FileType fileType = matchFileType(filePath);
|
||||
QString adjustedFilePath = filePath;
|
||||
|
||||
if(fileType == GZip || fileType == BZip2 || fileType == XZ)
|
||||
{
|
||||
adjustedFilePath = decompressToTemporaryFile(filePath, fileType);
|
||||
|
||||
if(adjustedFilePath.isEmpty())
|
||||
{
|
||||
qWarning() << tr("Could not decompress '%1'!").arg(filePath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fileType = matchFileType(adjustedFilePath);
|
||||
}
|
||||
|
||||
if(fileType == Unknown)
|
||||
{
|
||||
qWarning() << tr("Could not match file type of '%1'!").arg(filePath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!loadPlugin(fileType))
|
||||
{
|
||||
QMessageBox::critical(0, tr("Critical"), tr("Could not load plug-in for file type '%1'!").arg(fileTypeName(fileType)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_plugins.value(fileType)->loadDocument(adjustedFilePath);
|
||||
}
|
||||
|
||||
SettingsWidget* PluginHandler::createSettingsWidget(FileType fileType, QWidget* parent)
|
||||
{
|
||||
return loadPlugin(fileType) ? m_plugins.value(fileType)->createSettingsWidget(parent) : 0;
|
||||
}
|
||||
|
||||
PluginHandler::PluginHandler(QObject* parent) : QObject(parent),
|
||||
m_plugins()
|
||||
{
|
||||
#ifdef WITH_IMAGE
|
||||
#ifdef STATIC_IMAGE_PLUGIN
|
||||
m_objectNames.insertMulti(Image, QLatin1String("ImagePlugin"));
|
||||
#else
|
||||
m_fileNames.insertMulti(Image, QLatin1String(IMAGE_PLUGIN_NAME));
|
||||
#endif // STATIC_IMAGE_PLUGIN
|
||||
#endif // WITH_IMAGE
|
||||
|
||||
#ifdef WITH_FITZ
|
||||
#ifdef STATIC_FITZ_PLUGIN
|
||||
m_objectNames.insertMulti(PDF, QLatin1String("FitzPlugin"));
|
||||
m_objectNames.insertMulti(EPUB, QLatin1String("FitzPlugin"));
|
||||
m_objectNames.insertMulti(XPS, QLatin1String("FitzPlugin"));
|
||||
m_objectNames.insertMulti(FB2, QLatin1String("FitzPlugin"));
|
||||
m_objectNames.insertMulti(CBZ, QLatin1String("FitzPlugin"));
|
||||
#else
|
||||
m_fileNames.insertMulti(PDF, QLatin1String(FITZ_PLUGIN_NAME));
|
||||
m_fileNames.insertMulti(EPUB, QLatin1String(FITZ_PLUGIN_NAME));
|
||||
m_fileNames.insertMulti(XPS, QLatin1String(FITZ_PLUGIN_NAME));
|
||||
m_fileNames.insertMulti(FB2, QLatin1String(FITZ_PLUGIN_NAME));
|
||||
m_fileNames.insertMulti(CBZ, QLatin1String(FITZ_PLUGIN_NAME));
|
||||
#endif // STATIC_FITZ_PLUGIN
|
||||
#endif // WITH_FITZ
|
||||
|
||||
#ifdef WITH_PDF
|
||||
#ifdef STATIC_PDF_PLUGIN
|
||||
m_objectNames.insertMulti(PDF, QLatin1String("PdfPlugin"));
|
||||
#else
|
||||
m_fileNames.insertMulti(PDF, QLatin1String(PDF_PLUGIN_NAME));
|
||||
#endif // STATIC_PDF_PLUGIN
|
||||
#endif // WITH_PDF
|
||||
|
||||
#ifdef WITH_PS
|
||||
#ifdef STATIC_PS_PLUGIN
|
||||
m_objectNames.insertMulti(PS, QLatin1String("PsPlugin"));
|
||||
#else
|
||||
m_fileNames.insertMulti(PS, QLatin1String(PS_PLUGIN_NAME));
|
||||
#endif // STATIC_PS_PLUGIN
|
||||
#endif // WITH_PS
|
||||
|
||||
#ifdef WITH_DJVU
|
||||
#ifdef STATIC_DJVU_PLUGIN
|
||||
m_objectNames.insertMulti(DjVu, QLatin1String("DjVuPlugin"));
|
||||
#else
|
||||
m_fileNames.insertMulti(DjVu, QLatin1String(DJVU_PLUGIN_NAME));
|
||||
#endif // STATIC_DJVU_PLUGIN
|
||||
#endif // WITH_DJVU
|
||||
}
|
||||
|
||||
bool PluginHandler::loadPlugin(FileType fileType)
|
||||
{
|
||||
if(m_plugins.contains(fileType))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach(const QString& objectName, m_objectNames.values(fileType))
|
||||
{
|
||||
if(Plugin* plugin = ::loadStaticPlugin(objectName))
|
||||
{
|
||||
m_plugins.insert(fileType, plugin);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(const QString& fileName, m_fileNames.values(fileType))
|
||||
{
|
||||
if(Plugin* plugin = ::loadPlugin(fileName))
|
||||
{
|
||||
m_plugins.insert(fileType, plugin);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#ifdef STATIC_IMAGE_PLUGIN
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
Q_IMPORT_PLUGIN(qpdfview_image)
|
||||
#else
|
||||
Q_IMPORT_PLUGIN(ImagePlugin)
|
||||
#endif // QT_VERSION
|
||||
#endif // STATIC_IMAGE_PLUGIN
|
||||
|
||||
#ifdef STATIC_FITZ_PLUGIN
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
Q_IMPORT_PLUGIN(qpdfview_fitz)
|
||||
#else
|
||||
Q_IMPORT_PLUGIN(FitzPlugin)
|
||||
#endif // QT_VERSION
|
||||
#endif // STATIC_FITZ_PLUGIN
|
||||
|
||||
#ifdef STATIC_PDF_PLUGIN
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
Q_IMPORT_PLUGIN(qpdfview_pdf)
|
||||
#else
|
||||
Q_IMPORT_PLUGIN(PdfPlugin)
|
||||
#endif // QT_VERSION
|
||||
#endif // STATIC_PDF_PLUGIN
|
||||
|
||||
#ifdef STATIC_PS_PLUGIN
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
Q_IMPORT_PLUGIN(qpdfview_ps)
|
||||
#else
|
||||
Q_IMPORT_PLUGIN(PsPlugin)
|
||||
#endif // QT_VERSION
|
||||
#endif // STATIC_PS_PLUGIN
|
||||
|
||||
#ifdef STATIC_DJVU_PLUGIN
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
Q_IMPORT_PLUGIN(qpdfview_djvu)
|
||||
#else
|
||||
Q_IMPORT_PLUGIN(DjVuPlugin)
|
||||
#endif // QT_VERSION
|
||||
#endif // STATIC_DJVU_PLUGIN
|
93
sources/pluginhandler.h
Parasts fails
93
sources/pluginhandler.h
Parasts fails
@ -0,0 +1,93 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 S. Razi Alavizadeh
|
||||
Copyright 2012-2013, 2017, 2018 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PLUGINHANDLER_H
|
||||
#define PLUGINHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
|
||||
class QString;
|
||||
class QWidget;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
class SettingsWidget;
|
||||
class Plugin;
|
||||
|
||||
class PluginHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static PluginHandler* instance();
|
||||
~PluginHandler();
|
||||
|
||||
enum FileType
|
||||
{
|
||||
Unknown = 0,
|
||||
PDF,
|
||||
PS,
|
||||
DjVu,
|
||||
Image,
|
||||
GZip,
|
||||
BZip2,
|
||||
XZ,
|
||||
ZIP,
|
||||
EPUB,
|
||||
XPS,
|
||||
FB2,
|
||||
CBZ
|
||||
};
|
||||
|
||||
static QLatin1String fileTypeName(FileType fileType);
|
||||
|
||||
static QStringList openFilter();
|
||||
|
||||
Model::Document* loadDocument(const QString& filePath);
|
||||
|
||||
SettingsWidget* createSettingsWidget(FileType fileType, QWidget* parent = 0);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PluginHandler)
|
||||
|
||||
static PluginHandler* s_instance;
|
||||
PluginHandler(QObject* parent = 0);
|
||||
|
||||
QMap< FileType, Plugin* > m_plugins;
|
||||
|
||||
QMultiMap< FileType, QString > m_objectNames;
|
||||
QMultiMap< FileType, QString > m_fileNames;
|
||||
|
||||
bool loadPlugin(FileType fileType);
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // PLUGINHANDLER_H
|
640
sources/presentationview.cpp
Parasts fails
640
sources/presentationview.cpp
Parasts fails
@ -0,0 +1,640 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "presentationview.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QShortcut>
|
||||
#include <QTimer>
|
||||
|
||||
#include "settings.h"
|
||||
#include "model.h"
|
||||
#include "pageitem.h"
|
||||
#include "documentview.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace qpdfview;
|
||||
|
||||
inline void adjustScaleFactor(RenderParam& renderParam, qreal scaleFactor)
|
||||
{
|
||||
if(!qFuzzyCompare(renderParam.scaleFactor(), scaleFactor))
|
||||
{
|
||||
renderParam.setScaleFactor(scaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
Settings* PresentationView::s_settings = 0;
|
||||
|
||||
PresentationView::PresentationView(const QVector< Model::Page* >& pages, QWidget* parent) : QGraphicsView(parent),
|
||||
m_prefetchTimer(0),
|
||||
m_pages(pages),
|
||||
m_currentPage(1),
|
||||
m_past(),
|
||||
m_future(),
|
||||
m_scaleMode(FitToPageSizeMode),
|
||||
m_scaleFactor(1.0),
|
||||
m_rotation(RotateBy0),
|
||||
m_renderFlags(0),
|
||||
m_pageItems()
|
||||
{
|
||||
if(s_settings == 0)
|
||||
{
|
||||
s_settings = Settings::instance();
|
||||
}
|
||||
|
||||
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
|
||||
setWindowState(windowState() | Qt::WindowFullScreen);
|
||||
|
||||
setFrameShape(QFrame::NoFrame);
|
||||
|
||||
setAcceptDrops(false);
|
||||
setDragMode(QGraphicsView::ScrollHandDrag);
|
||||
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
setScene(new QGraphicsScene(this));
|
||||
|
||||
preparePages();
|
||||
prepareBackground();
|
||||
|
||||
// prefetch
|
||||
|
||||
m_prefetchTimer = new QTimer(this);
|
||||
m_prefetchTimer->setInterval(250);
|
||||
m_prefetchTimer->setSingleShot(true);
|
||||
|
||||
connect(this, SIGNAL(currentPageChanged(int)), m_prefetchTimer, SLOT(start()));
|
||||
connect(this, SIGNAL(scaleModeChanged(ScaleMode)), m_prefetchTimer, SLOT(start()));
|
||||
connect(this, SIGNAL(scaleFactorChanged(qreal)), m_prefetchTimer, SLOT(start()));
|
||||
connect(this, SIGNAL(rotationChanged(Rotation)), m_prefetchTimer, SLOT(start()));
|
||||
connect(this, SIGNAL(renderFlagsChanged(qpdfview::RenderFlags)), m_prefetchTimer, SLOT(start()));
|
||||
|
||||
connect(m_prefetchTimer, SIGNAL(timeout()), SLOT(on_prefetch_timeout()));
|
||||
|
||||
if(s_settings->documentView().prefetch())
|
||||
{
|
||||
m_prefetchTimer->blockSignals(false);
|
||||
m_prefetchTimer->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_prefetchTimer->blockSignals(true);
|
||||
m_prefetchTimer->stop();
|
||||
}
|
||||
|
||||
prepareScene();
|
||||
prepareView();
|
||||
}
|
||||
|
||||
PresentationView::~PresentationView()
|
||||
{
|
||||
qDeleteAll(m_pageItems);
|
||||
}
|
||||
|
||||
void PresentationView::setScaleMode(ScaleMode scaleMode)
|
||||
{
|
||||
if(m_scaleMode != scaleMode && scaleMode >= 0 && scaleMode < NumberOfScaleModes)
|
||||
{
|
||||
m_scaleMode = scaleMode;
|
||||
|
||||
prepareScene();
|
||||
prepareView();
|
||||
|
||||
emit scaleModeChanged(m_scaleMode);
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::setScaleFactor(qreal scaleFactor)
|
||||
{
|
||||
if(!qFuzzyCompare(m_scaleFactor, scaleFactor)
|
||||
&& scaleFactor >= s_settings->documentView().minimumScaleFactor()
|
||||
&& scaleFactor <= s_settings->documentView().maximumScaleFactor())
|
||||
{
|
||||
m_scaleFactor = scaleFactor;
|
||||
|
||||
if(m_scaleMode == ScaleFactorMode)
|
||||
{
|
||||
prepareScene();
|
||||
prepareView();
|
||||
}
|
||||
|
||||
emit scaleFactorChanged(m_scaleFactor);
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::setRotation(Rotation rotation)
|
||||
{
|
||||
if(m_rotation != rotation)
|
||||
{
|
||||
m_rotation = rotation;
|
||||
|
||||
prepareScene();
|
||||
prepareView();
|
||||
|
||||
emit rotationChanged(m_rotation);
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::setRenderFlags(qpdfview::RenderFlags renderFlags)
|
||||
{
|
||||
if(m_renderFlags != renderFlags)
|
||||
{
|
||||
const qpdfview::RenderFlags changedFlags = m_renderFlags ^ renderFlags;
|
||||
|
||||
m_renderFlags = renderFlags;
|
||||
|
||||
prepareScene();
|
||||
prepareView();
|
||||
|
||||
if(changedFlags.testFlag(InvertColors))
|
||||
{
|
||||
prepareBackground();
|
||||
}
|
||||
|
||||
emit renderFlagsChanged(m_renderFlags);
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::show()
|
||||
{
|
||||
QWidget::show();
|
||||
|
||||
prepareView();
|
||||
}
|
||||
|
||||
void PresentationView::previousPage()
|
||||
{
|
||||
jumpToPage(m_currentPage - 1);
|
||||
}
|
||||
|
||||
void PresentationView::nextPage()
|
||||
{
|
||||
jumpToPage(m_currentPage + 1);
|
||||
}
|
||||
|
||||
void PresentationView::firstPage()
|
||||
{
|
||||
jumpToPage(1);
|
||||
}
|
||||
|
||||
void PresentationView::lastPage()
|
||||
{
|
||||
jumpToPage(m_pages.count());
|
||||
}
|
||||
|
||||
void PresentationView::jumpToPage(int page, bool trackChange)
|
||||
{
|
||||
if(m_currentPage != page && page >= 1 && page <= m_pages.count())
|
||||
{
|
||||
if(trackChange)
|
||||
{
|
||||
m_past.append(m_currentPage);
|
||||
}
|
||||
|
||||
m_currentPage = page;
|
||||
|
||||
prepareView();
|
||||
|
||||
emit currentPageChanged(m_currentPage, trackChange);
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::jumpBackward()
|
||||
{
|
||||
if(!m_past.isEmpty())
|
||||
{
|
||||
m_future.prepend(m_currentPage);
|
||||
|
||||
jumpToPage(m_past.takeLast(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::jumpForward()
|
||||
{
|
||||
if(!m_future.isEmpty())
|
||||
{
|
||||
m_past.append(m_currentPage);
|
||||
|
||||
jumpToPage(m_future.takeFirst(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::zoomIn()
|
||||
{
|
||||
if(scaleMode() != ScaleFactorMode)
|
||||
{
|
||||
const qreal currentScaleFactor = m_pageItems.at(m_currentPage - 1)->renderParam().scaleFactor();
|
||||
|
||||
setScaleFactor(qMin(currentScaleFactor * s_settings->documentView().zoomFactor(),
|
||||
s_settings->documentView().maximumScaleFactor()));
|
||||
|
||||
setScaleMode(ScaleFactorMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
setScaleFactor(qMin(m_scaleFactor * s_settings->documentView().zoomFactor(),
|
||||
s_settings->documentView().maximumScaleFactor()));
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::zoomOut()
|
||||
{
|
||||
if(scaleMode() != ScaleFactorMode)
|
||||
{
|
||||
const qreal currentScaleFactor = m_pageItems.at(m_currentPage - 1)->renderParam().scaleFactor();
|
||||
|
||||
setScaleFactor(qMax(currentScaleFactor / s_settings->documentView().zoomFactor(),
|
||||
s_settings->documentView().minimumScaleFactor()));
|
||||
|
||||
setScaleMode(ScaleFactorMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
setScaleFactor(qMax(m_scaleFactor / s_settings->documentView().zoomFactor(),
|
||||
s_settings->documentView().minimumScaleFactor()));
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::originalSize()
|
||||
{
|
||||
setScaleFactor(1.0);
|
||||
setScaleMode(ScaleFactorMode);
|
||||
}
|
||||
|
||||
void PresentationView::rotateLeft()
|
||||
{
|
||||
switch(m_rotation)
|
||||
{
|
||||
default:
|
||||
case RotateBy0:
|
||||
setRotation(RotateBy270);
|
||||
break;
|
||||
case RotateBy90:
|
||||
setRotation(RotateBy0);
|
||||
break;
|
||||
case RotateBy180:
|
||||
setRotation(RotateBy90);
|
||||
break;
|
||||
case RotateBy270:
|
||||
setRotation(RotateBy180);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::rotateRight()
|
||||
{
|
||||
switch(m_rotation)
|
||||
{
|
||||
default:
|
||||
case RotateBy0:
|
||||
setRotation(RotateBy90);
|
||||
break;
|
||||
case RotateBy90:
|
||||
setRotation(RotateBy180);
|
||||
break;
|
||||
case RotateBy180:
|
||||
setRotation(RotateBy270);
|
||||
break;
|
||||
case RotateBy270:
|
||||
setRotation(RotateBy0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::on_prefetch_timeout()
|
||||
{
|
||||
int fromPage = m_currentPage, toPage = m_currentPage;
|
||||
|
||||
fromPage -= s_settings->documentView().prefetchDistance() / 2;
|
||||
toPage += s_settings->documentView().prefetchDistance();
|
||||
|
||||
fromPage = qMax(fromPage, 1);
|
||||
toPage = qMin(toPage, m_pages.count());
|
||||
|
||||
const int maxCost = toPage - fromPage + 1;
|
||||
int cost = 0;
|
||||
|
||||
for(int index = m_currentPage - 1; index <= toPage - 1; ++index)
|
||||
{
|
||||
cost += m_pageItems.at(index)->startRender(true);
|
||||
|
||||
if(cost >= maxCost)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for(int index = m_currentPage - 1; index >= fromPage - 1; --index)
|
||||
{
|
||||
cost += m_pageItems.at(index)->startRender(true);
|
||||
|
||||
if(cost >= maxCost)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::on_pages_cropRectChanged()
|
||||
{
|
||||
prepareScene();
|
||||
prepareView();
|
||||
}
|
||||
|
||||
void PresentationView::on_pages_linkClicked(bool newTab, int page, qreal left, qreal top)
|
||||
{
|
||||
Q_UNUSED(newTab);
|
||||
Q_UNUSED(left);
|
||||
Q_UNUSED(top);
|
||||
|
||||
page = qMax(page, 1);
|
||||
page = qMin(page, m_pages.count());
|
||||
|
||||
jumpToPage(page, true);
|
||||
}
|
||||
|
||||
void PresentationView::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QGraphicsView::resizeEvent(event);
|
||||
|
||||
prepareScene();
|
||||
prepareView();
|
||||
}
|
||||
|
||||
void PresentationView::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
switch(event->modifiers() + event->key())
|
||||
{
|
||||
case Qt::Key_PageUp:
|
||||
case Qt::Key_Up:
|
||||
case Qt::Key_Left:
|
||||
case Qt::Key_Backspace:
|
||||
previousPage();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::Key_PageDown:
|
||||
case Qt::Key_Down:
|
||||
case Qt::Key_Right:
|
||||
case Qt::Key_Space:
|
||||
nextPage();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::Key_Home:
|
||||
firstPage();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::Key_End:
|
||||
lastPage();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_Return:
|
||||
jumpBackward();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::SHIFT + Qt::Key_Return:
|
||||
jumpForward();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_0:
|
||||
originalSize();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_9:
|
||||
setScaleMode(FitToPageWidthMode);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_8:
|
||||
setScaleMode(FitToPageSizeMode);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_Up:
|
||||
zoomIn();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_Down:
|
||||
zoomOut();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_Left:
|
||||
rotateLeft();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_Right:
|
||||
rotateRight();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_I:
|
||||
setRenderFlags(renderFlags() ^ InvertColors);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::Key_U:
|
||||
setRenderFlags(renderFlags() ^ ConvertToGrayscale);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::CTRL + Qt::SHIFT + Qt::Key_U:
|
||||
setRenderFlags(renderFlags() ^ TrimMargins);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
case Qt::Key_F12:
|
||||
case Qt::Key_Escape:
|
||||
close();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void PresentationView::wheelEvent(QWheelEvent* event)
|
||||
{
|
||||
if(event->modifiers() == s_settings->documentView().zoomModifiers())
|
||||
{
|
||||
if(event->delta() > 0)
|
||||
{
|
||||
zoomIn();
|
||||
}
|
||||
else
|
||||
{
|
||||
zoomOut();
|
||||
}
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
else if(event->modifiers() == s_settings->documentView().rotateModifiers())
|
||||
{
|
||||
if(event->delta() > 0)
|
||||
{
|
||||
rotateLeft();
|
||||
}
|
||||
else
|
||||
{
|
||||
rotateRight();
|
||||
}
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
else if(event->modifiers() == Qt::NoModifier)
|
||||
{
|
||||
if(event->delta() > 0 && m_currentPage != 1)
|
||||
{
|
||||
previousPage();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
else if(event->delta() < 0 && m_currentPage != m_pages.count())
|
||||
{
|
||||
nextPage();
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QGraphicsView::wheelEvent(event);
|
||||
}
|
||||
|
||||
void PresentationView::preparePages()
|
||||
{
|
||||
for(int index = 0; index < m_pages.count(); ++index)
|
||||
{
|
||||
PageItem* page = new PageItem(m_pages.at(index), index, PageItem::PresentationMode);
|
||||
|
||||
scene()->addItem(page);
|
||||
m_pageItems.append(page);
|
||||
|
||||
connect(page, SIGNAL(cropRectChanged()), SLOT(on_pages_cropRectChanged()));
|
||||
|
||||
connect(page, SIGNAL(linkClicked(bool,int,qreal,qreal)), SLOT(on_pages_linkClicked(bool,int,qreal,qreal)));
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::prepareBackground()
|
||||
{
|
||||
QColor backgroundColor = s_settings->presentationView().backgroundColor();
|
||||
|
||||
if(!backgroundColor.isValid())
|
||||
{
|
||||
backgroundColor = s_settings->pageItem().paperColor();
|
||||
}
|
||||
|
||||
if(m_renderFlags.testFlag(InvertColors))
|
||||
{
|
||||
backgroundColor.setRgb(~backgroundColor.rgb());
|
||||
}
|
||||
|
||||
scene()->setBackgroundBrush(QBrush(backgroundColor));
|
||||
}
|
||||
|
||||
void PresentationView::prepareScene()
|
||||
{
|
||||
RenderParam renderParam(logicalDpiX(), logicalDpiY(), 1.0,
|
||||
scaleFactor(), rotation(), renderFlags());
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,1,0)
|
||||
|
||||
if(s_settings->pageItem().useDevicePixelRatio())
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,6,0)
|
||||
|
||||
renderParam.setDevicePixelRatio(devicePixelRatioF());
|
||||
|
||||
#else
|
||||
|
||||
renderParam.setDevicePixelRatio(devicePixelRatio());
|
||||
|
||||
#endif // QT_VERSION
|
||||
}
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
const qreal visibleWidth = viewport()->width();
|
||||
const qreal visibleHeight = viewport()->height();
|
||||
|
||||
foreach(PageItem* page, m_pageItems)
|
||||
{
|
||||
const QSizeF displayedSize = page->displayedSize(renderParam);
|
||||
|
||||
if(m_scaleMode == FitToPageWidthMode)
|
||||
{
|
||||
adjustScaleFactor(renderParam, visibleWidth / displayedSize.width());
|
||||
}
|
||||
else if(m_scaleMode == FitToPageSizeMode)
|
||||
{
|
||||
adjustScaleFactor(renderParam, qMin(visibleWidth / displayedSize.width(), visibleHeight / displayedSize.height()));
|
||||
}
|
||||
|
||||
page->setRenderParam(renderParam);
|
||||
}
|
||||
}
|
||||
|
||||
void PresentationView::prepareView()
|
||||
{
|
||||
for(int index = 0; index < m_pageItems.count(); ++index)
|
||||
{
|
||||
PageItem* page = m_pageItems.at(index);
|
||||
|
||||
if(index == m_currentPage - 1)
|
||||
{
|
||||
page->setVisible(true);
|
||||
|
||||
setSceneRect(page->boundingRect().translated(page->pos()));
|
||||
}
|
||||
else
|
||||
{
|
||||
page->setVisible(false);
|
||||
|
||||
page->cancelRender();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
} // qpdfview
|
137
sources/presentationview.h
Parasts fails
137
sources/presentationview.h
Parasts fails
@ -0,0 +1,137 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PRESENTATIONVIEW_H
|
||||
#define PRESENTATIONVIEW_H
|
||||
|
||||
#include <QGraphicsView>
|
||||
|
||||
#include "renderparam.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class Page;
|
||||
}
|
||||
|
||||
class Settings;
|
||||
class PageItem;
|
||||
|
||||
class PresentationView : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PresentationView(const QVector< Model::Page* >& pages, QWidget* parent = 0);
|
||||
~PresentationView();
|
||||
|
||||
int numberOfPages() const { return m_pages.count(); }
|
||||
int currentPage() const { return m_currentPage; }
|
||||
|
||||
ScaleMode scaleMode() const { return m_scaleMode; }
|
||||
void setScaleMode(ScaleMode scaleMode);
|
||||
|
||||
qreal scaleFactor() const { return m_scaleFactor; }
|
||||
void setScaleFactor(qreal scaleFactor);
|
||||
|
||||
Rotation rotation() const { return m_rotation; }
|
||||
void setRotation(Rotation rotation);
|
||||
|
||||
qpdfview::RenderFlags renderFlags() const { return m_renderFlags; }
|
||||
void setRenderFlags(qpdfview::RenderFlags renderFlags);
|
||||
|
||||
signals:
|
||||
void currentPageChanged(int currentPage, bool trackChange = false);
|
||||
|
||||
void scaleModeChanged(ScaleMode scaleMode);
|
||||
void scaleFactorChanged(qreal scaleFactor);
|
||||
void rotationChanged(Rotation rotation);
|
||||
|
||||
void renderFlagsChanged(qpdfview::RenderFlags renderFlags);
|
||||
|
||||
public slots:
|
||||
void show();
|
||||
|
||||
void previousPage();
|
||||
void nextPage();
|
||||
void firstPage();
|
||||
void lastPage();
|
||||
|
||||
void jumpToPage(int page, bool trackChange = true);
|
||||
|
||||
void jumpBackward();
|
||||
void jumpForward();
|
||||
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
void originalSize();
|
||||
|
||||
void rotateLeft();
|
||||
void rotateRight();
|
||||
|
||||
protected slots:
|
||||
void on_prefetch_timeout();
|
||||
|
||||
void on_pages_cropRectChanged();
|
||||
|
||||
void on_pages_linkClicked(bool newTab, int page, qreal left, qreal top);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void wheelEvent(QWheelEvent* event);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PresentationView)
|
||||
|
||||
static Settings* s_settings;
|
||||
|
||||
QTimer* m_prefetchTimer;
|
||||
|
||||
QVector< Model::Page* > m_pages;
|
||||
|
||||
int m_currentPage;
|
||||
|
||||
QList< int > m_past;
|
||||
QList< int > m_future;
|
||||
|
||||
ScaleMode m_scaleMode;
|
||||
qreal m_scaleFactor;
|
||||
Rotation m_rotation;
|
||||
|
||||
qpdfview::RenderFlags m_renderFlags;
|
||||
|
||||
QVector< PageItem* > m_pageItems;
|
||||
|
||||
void preparePages();
|
||||
void prepareBackground();
|
||||
|
||||
void prepareScene();
|
||||
void prepareView();
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // PRESENTATIONVIEW_H
|
161
sources/printdialog.cpp
Parasts fails
161
sources/printdialog.cpp
Parasts fails
@ -0,0 +1,161 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "printdialog.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QComboBox>
|
||||
#include <QFormLayout>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
Settings* PrintDialog::s_settings = 0;
|
||||
|
||||
QPrinter* PrintDialog::createPrinter()
|
||||
{
|
||||
QPrinter* printer = new QPrinter();
|
||||
|
||||
const Settings::PrintDialog& settings = Settings::instance()->printDialog();
|
||||
printer->setCollateCopies(settings.collateCopies());
|
||||
printer->setPageOrder(settings.pageOrder());
|
||||
printer->setOrientation(settings.orientation());
|
||||
printer->setColorMode(settings.colorMode());
|
||||
printer->setDuplex(settings.duplex());
|
||||
|
||||
return printer;
|
||||
}
|
||||
|
||||
PrintDialog::PrintDialog(QPrinter* printer, QWidget* parent) : QPrintDialog(printer, parent)
|
||||
{
|
||||
if(s_settings == 0)
|
||||
{
|
||||
s_settings = Settings::instance();
|
||||
}
|
||||
|
||||
// print options
|
||||
|
||||
m_printOptionsWidget = new QWidget(this);
|
||||
m_printOptionsLayout = new QFormLayout(m_printOptionsWidget);
|
||||
|
||||
m_fitToPageCheckBox = new QCheckBox(this);
|
||||
m_fitToPageCheckBox->setChecked(s_settings->printDialog().fitToPage());
|
||||
|
||||
m_printOptionsLayout->addRow(tr("Fit to page:"), m_fitToPageCheckBox);
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
|
||||
|
||||
m_pageRangesLineEdit = new QLineEdit(this);
|
||||
|
||||
m_printOptionsLayout->addRow(tr("Page ranges:"), m_pageRangesLineEdit);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
|
||||
|
||||
m_pageSetComboBox = new QComboBox(this);
|
||||
m_pageSetComboBox->addItem(tr("All pages"), static_cast< uint >(PrintOptions::AllPages));
|
||||
m_pageSetComboBox->addItem(tr("Even pages"), static_cast< uint >(PrintOptions::EvenPages));
|
||||
m_pageSetComboBox->addItem(tr("Odd pages"), static_cast< uint >(PrintOptions::OddPages));
|
||||
m_pageSetComboBox->setCurrentIndex(m_pageSetComboBox->findData(static_cast< uint >(s_settings->printDialog().pageSet())));
|
||||
|
||||
m_printOptionsLayout->addRow(tr("Page set:"), m_pageSetComboBox);
|
||||
|
||||
m_numberUpComboBox = new QComboBox(this);
|
||||
m_numberUpComboBox->addItem(tr("Single page"), static_cast< uint >(PrintOptions::SinglePage));
|
||||
m_numberUpComboBox->addItem(tr("Two pages"), static_cast< uint >(PrintOptions::TwoPages));
|
||||
m_numberUpComboBox->addItem(tr("Four pages"), static_cast< uint >(PrintOptions::FourPages));
|
||||
m_numberUpComboBox->addItem(tr("Six pages"), static_cast< uint >(PrintOptions::SixPages));
|
||||
m_numberUpComboBox->addItem(tr("Nine pages"), static_cast< uint >(PrintOptions::NinePages));
|
||||
m_numberUpComboBox->addItem(tr("Sixteen pages"), static_cast< uint >(PrintOptions::SixteenPages));
|
||||
m_numberUpComboBox->setCurrentIndex(m_numberUpComboBox->findData(static_cast< uint >(s_settings->printDialog().numberUp())));
|
||||
|
||||
m_printOptionsLayout->addRow(tr("Number-up:"), m_numberUpComboBox);
|
||||
|
||||
m_numberUpLayoutComboBox = new QComboBox(this);
|
||||
m_numberUpLayoutComboBox->addItem(tr("Bottom to top and left to right"), static_cast< uint >(PrintOptions::BottomTopLeftRight));
|
||||
m_numberUpLayoutComboBox->addItem(tr("Bottom to top and right to left"), static_cast< uint >(PrintOptions::BottomTopRightLeft));
|
||||
m_numberUpLayoutComboBox->addItem(tr("Left to right and bottom to top"), static_cast< uint >(PrintOptions::LeftRightBottomTop));
|
||||
m_numberUpLayoutComboBox->addItem(tr("Left to right and top to bottom"), static_cast< uint >(PrintOptions::LeftRightTopBottom));
|
||||
m_numberUpLayoutComboBox->addItem(tr("Right to left and bottom to top"), static_cast< uint >(PrintOptions::RightLeftBottomTop));
|
||||
m_numberUpLayoutComboBox->addItem(tr("Right to left and top to bottom"), static_cast< uint >(PrintOptions::RightLeftTopBottom));
|
||||
m_numberUpLayoutComboBox->addItem(tr("Top to bottom and left to right"), static_cast< uint >(PrintOptions::TopBottomLeftRight));
|
||||
m_numberUpLayoutComboBox->addItem(tr("Top to bottom and right to left"), static_cast< uint >(PrintOptions::TopBottomRightLeft));
|
||||
m_numberUpLayoutComboBox->setCurrentIndex(m_numberUpLayoutComboBox->findData(static_cast< uint >(s_settings->printDialog().numberUpLayout())));
|
||||
|
||||
m_printOptionsLayout->addRow(tr("Number-up layout:"), m_numberUpLayoutComboBox);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
m_printOptionsWidget->setWindowTitle(tr("Extended options"));
|
||||
setOptionTabs(QList< QWidget* >() << m_printOptionsWidget);
|
||||
}
|
||||
|
||||
PrintOptions PrintDialog::printOptions() const
|
||||
{
|
||||
PrintOptions printOptions;
|
||||
|
||||
printOptions.fitToPage = m_fitToPageCheckBox->isChecked();
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
|
||||
|
||||
printOptions.pageRanges = m_pageRangesLineEdit->text();
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
|
||||
|
||||
printOptions.pageSet = static_cast< PrintOptions::PageSet >(m_pageSetComboBox->itemData(m_pageSetComboBox->currentIndex()).toUInt());
|
||||
|
||||
printOptions.numberUp = static_cast< PrintOptions::NumberUp >(m_numberUpComboBox->itemData(m_numberUpComboBox->currentIndex()).toUInt());
|
||||
printOptions.numberUpLayout = static_cast< PrintOptions::NumberUpLayout >(m_numberUpLayoutComboBox->itemData(m_numberUpLayoutComboBox->currentIndex()).toUInt());
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
return printOptions;
|
||||
}
|
||||
|
||||
void PrintDialog::accept()
|
||||
{
|
||||
QPrintDialog::accept();
|
||||
|
||||
s_settings->printDialog().setCollateCopies(printer()->collateCopies());
|
||||
s_settings->printDialog().setPageOrder(printer()->pageOrder());
|
||||
s_settings->printDialog().setOrientation(printer()->orientation());
|
||||
s_settings->printDialog().setColorMode(printer()->colorMode());
|
||||
s_settings->printDialog().setDuplex(printer()->duplex());
|
||||
|
||||
s_settings->printDialog().setFitToPage(m_fitToPageCheckBox->isChecked());
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
|
||||
|
||||
s_settings->printDialog().setPageSet(static_cast< PrintOptions::PageSet >(m_pageSetComboBox->itemData(m_pageSetComboBox->currentIndex()).toUInt()));
|
||||
|
||||
s_settings->printDialog().setNumberUp(static_cast< PrintOptions::NumberUp >(m_numberUpComboBox->itemData(m_numberUpComboBox->currentIndex()).toUInt()));
|
||||
s_settings->printDialog().setNumberUpLayout(static_cast< PrintOptions::NumberUpLayout >(m_numberUpLayoutComboBox->itemData(m_numberUpLayoutComboBox->currentIndex()).toUInt()));
|
||||
|
||||
#endif // QT_VERSION
|
||||
}
|
||||
|
||||
} // qpdfview
|
82
sources/printdialog.h
Parasts fails
82
sources/printdialog.h
Parasts fails
@ -0,0 +1,82 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PRINTDIALOG_H
|
||||
#define PRINTDIALOG_H
|
||||
|
||||
#include <QPrintDialog>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QFormLayout;
|
||||
class QLineEdit;
|
||||
class QPrinter;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
struct PrintOptions;
|
||||
class Settings;
|
||||
|
||||
class PrintDialog : public QPrintDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QPrinter* createPrinter();
|
||||
|
||||
PrintDialog(QPrinter* printer, QWidget* parent = 0);
|
||||
|
||||
PrintOptions printOptions() const;
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PrintDialog)
|
||||
|
||||
static Settings* s_settings;
|
||||
|
||||
QWidget* m_printOptionsWidget;
|
||||
QFormLayout* m_printOptionsLayout;
|
||||
|
||||
QCheckBox* m_fitToPageCheckBox;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,11,0)
|
||||
|
||||
QLineEdit* m_pageRangesLineEdit;
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
|
||||
|
||||
QComboBox* m_pageSetComboBox;
|
||||
|
||||
QComboBox* m_numberUpComboBox;
|
||||
QComboBox* m_numberUpLayoutComboBox;
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // PRINTDIALOG_H
|
84
sources/printoptions.h
Parasts fails
84
sources/printoptions.h
Parasts fails
@ -0,0 +1,84 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Adam Reichold
|
||||
Copyright 2013 Alexander Volkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PRINTOPTIONS_H
|
||||
#define PRINTOPTIONS_H
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
struct PrintOptions
|
||||
{
|
||||
bool fitToPage;
|
||||
|
||||
QString pageRanges;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
|
||||
|
||||
enum PageSet
|
||||
{
|
||||
AllPages = 0,
|
||||
EvenPages = 1,
|
||||
OddPages = 2
|
||||
};
|
||||
|
||||
PageSet pageSet;
|
||||
|
||||
enum NumberUp
|
||||
{
|
||||
SinglePage = 0,
|
||||
TwoPages = 1,
|
||||
FourPages = 2,
|
||||
SixPages = 3,
|
||||
NinePages = 4,
|
||||
SixteenPages = 5
|
||||
};
|
||||
|
||||
NumberUp numberUp;
|
||||
|
||||
enum NumberUpLayout
|
||||
{
|
||||
BottomTopLeftRight = 0,
|
||||
BottomTopRightLeft = 1,
|
||||
LeftRightBottomTop = 2,
|
||||
LeftRightTopBottom = 3,
|
||||
RightLeftBottomTop = 4,
|
||||
RightLeftTopBottom = 5,
|
||||
TopBottomLeftRight = 6,
|
||||
TopBottomRightLeft = 7
|
||||
};
|
||||
|
||||
NumberUpLayout numberUpLayout;
|
||||
|
||||
PrintOptions() : fitToPage(false), pageRanges(), pageSet(AllPages), numberUp(SinglePage), numberUpLayout(LeftRightTopBottom) {}
|
||||
|
||||
#else
|
||||
|
||||
PrintOptions() : fitToPage(false), pageRanges() {}
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // PRINTOPTIONS_H
|
325
sources/psmodel.cpp
Parasts fails
325
sources/psmodel.cpp
Parasts fails
@ -0,0 +1,325 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Alexander Volkov
|
||||
Copyright 2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "psmodel.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFormLayout>
|
||||
#include <qmath.h>
|
||||
#include <QSettings>
|
||||
#include <QSpinBox>
|
||||
|
||||
#include <libspectre/spectre-document.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace qpdfview;
|
||||
using namespace qpdfview::Model;
|
||||
|
||||
namespace Defaults
|
||||
{
|
||||
|
||||
const int graphicsAntialiasBits = 4;
|
||||
const int textAntialiasBits = 2;
|
||||
|
||||
} // Defaults
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
|
||||
PsPage::PsPage(QMutex* mutex, SpectrePage* page, SpectreRenderContext* renderContext) :
|
||||
m_mutex(mutex),
|
||||
m_page(page),
|
||||
m_renderContext(renderContext)
|
||||
{
|
||||
}
|
||||
|
||||
PsPage::~PsPage()
|
||||
{
|
||||
spectre_page_free(m_page);
|
||||
m_page = 0;
|
||||
}
|
||||
|
||||
QSizeF PsPage::size() const
|
||||
{
|
||||
QMutexLocker mutexLocker(m_mutex);
|
||||
|
||||
int w;
|
||||
int h;
|
||||
|
||||
spectre_page_get_size(m_page, &w, &h);
|
||||
|
||||
return QSizeF(w, h);
|
||||
}
|
||||
|
||||
QImage PsPage::render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const
|
||||
{
|
||||
QMutexLocker mutexLocker(m_mutex);
|
||||
|
||||
double xscale;
|
||||
double yscale;
|
||||
|
||||
switch(rotation)
|
||||
{
|
||||
default:
|
||||
case RotateBy0:
|
||||
case RotateBy180:
|
||||
xscale = horizontalResolution / 72.0;
|
||||
yscale = verticalResolution / 72.0;
|
||||
break;
|
||||
case RotateBy90:
|
||||
case RotateBy270:
|
||||
xscale = verticalResolution / 72.0;
|
||||
yscale = horizontalResolution / 72.0;
|
||||
break;
|
||||
}
|
||||
|
||||
spectre_render_context_set_scale(m_renderContext, xscale, yscale);
|
||||
|
||||
switch(rotation)
|
||||
{
|
||||
default:
|
||||
case RotateBy0:
|
||||
spectre_render_context_set_rotation(m_renderContext, 0);
|
||||
break;
|
||||
case RotateBy90:
|
||||
spectre_render_context_set_rotation(m_renderContext, 90);
|
||||
break;
|
||||
case RotateBy180:
|
||||
spectre_render_context_set_rotation(m_renderContext, 180);
|
||||
break;
|
||||
case RotateBy270:
|
||||
spectre_render_context_set_rotation(m_renderContext, 270);
|
||||
break;
|
||||
}
|
||||
|
||||
int w;
|
||||
int h;
|
||||
|
||||
spectre_page_get_size(m_page, &w, &h);
|
||||
|
||||
w = qRound(w * xscale);
|
||||
h = qRound(h * yscale);
|
||||
|
||||
if(rotation == RotateBy90 || rotation == RotateBy270)
|
||||
{
|
||||
qSwap(w, h);
|
||||
}
|
||||
|
||||
unsigned char* pageData = 0;
|
||||
int rowLength = 0;
|
||||
|
||||
spectre_page_render(m_page, m_renderContext, &pageData, &rowLength);
|
||||
|
||||
if (spectre_page_status(m_page) != SPECTRE_STATUS_SUCCESS)
|
||||
{
|
||||
free(pageData);
|
||||
pageData = 0;
|
||||
|
||||
return QImage();
|
||||
}
|
||||
|
||||
QImage auxiliaryImage(pageData, rowLength / 4, h, QImage::Format_RGB32);
|
||||
QImage image(boundingRect.isNull() ? auxiliaryImage.copy(0, 0, w, h) : auxiliaryImage.copy(boundingRect));
|
||||
|
||||
free(pageData);
|
||||
pageData = 0;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
PsDocument::PsDocument(SpectreDocument* document, SpectreRenderContext* renderContext) :
|
||||
m_mutex(),
|
||||
m_document(document),
|
||||
m_renderContext(renderContext)
|
||||
{
|
||||
}
|
||||
|
||||
PsDocument::~PsDocument()
|
||||
{
|
||||
spectre_render_context_free(m_renderContext);
|
||||
m_renderContext = 0;
|
||||
|
||||
spectre_document_free(m_document);
|
||||
m_document = 0;
|
||||
}
|
||||
|
||||
int PsDocument::numberOfPages() const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
return spectre_document_get_n_pages(m_document);
|
||||
}
|
||||
|
||||
Page* PsDocument::page(int index) const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(SpectrePage* page = spectre_document_get_page(m_document, index))
|
||||
{
|
||||
return new PsPage(&m_mutex, page, m_renderContext);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QStringList PsDocument::saveFilter() const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(spectre_document_is_eps(m_document))
|
||||
{
|
||||
return QStringList() << QLatin1String("Encapsulated PostScript (*.eps)");
|
||||
}
|
||||
else
|
||||
{
|
||||
return QStringList() << QLatin1String("PostScript (*.ps)");
|
||||
}
|
||||
}
|
||||
|
||||
bool PsDocument::canSave() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PsDocument::save(const QString& filePath, bool withChanges) const
|
||||
{
|
||||
Q_UNUSED(withChanges)
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
spectre_document_save(m_document, QFile::encodeName(filePath));
|
||||
|
||||
return spectre_document_status(m_document) == SPECTRE_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
bool PsDocument::canBePrintedUsingCUPS() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Properties PsDocument::properties() const
|
||||
{
|
||||
Properties properties;
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
const QString title = QString::fromLocal8Bit(spectre_document_get_title(m_document));
|
||||
const QString createdFor = QString::fromLocal8Bit(spectre_document_get_for(m_document));
|
||||
const QString creator = QString::fromLocal8Bit(spectre_document_get_creator(m_document));
|
||||
const QString creationDate = QString::fromLocal8Bit(spectre_document_get_creation_date(m_document));
|
||||
const QString format = QString::fromLocal8Bit(spectre_document_get_format(m_document));
|
||||
const QString languageLevel = QString::number(spectre_document_get_language_level(m_document));
|
||||
|
||||
properties.push_back(qMakePair(tr("Title"), title));
|
||||
properties.push_back(qMakePair(tr("Created for"), createdFor));
|
||||
properties.push_back(qMakePair(tr("Creator"), creator));
|
||||
properties.push_back(qMakePair(tr("Creation date"), creationDate));
|
||||
properties.push_back(qMakePair(tr("Format"), format));
|
||||
properties.push_back(qMakePair(tr("Language level"), languageLevel));
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
} // Model
|
||||
|
||||
PsSettingsWidget::PsSettingsWidget(QSettings* settings, QWidget* parent) : SettingsWidget(parent),
|
||||
m_settings(settings)
|
||||
{
|
||||
m_layout = new QFormLayout(this);
|
||||
|
||||
// graphics antialias bits
|
||||
|
||||
m_graphicsAntialiasBitsSpinBox = new QSpinBox(this);
|
||||
m_graphicsAntialiasBitsSpinBox->setRange(1, 4);
|
||||
m_graphicsAntialiasBitsSpinBox->setValue(m_settings->value("graphicsAntialiasBits", Defaults::graphicsAntialiasBits).toInt());
|
||||
|
||||
m_layout->addRow(tr("Graphics antialias bits:"), m_graphicsAntialiasBitsSpinBox);
|
||||
|
||||
// text antialias bits
|
||||
|
||||
m_textAntialiasBitsSpinBox = new QSpinBox(this);
|
||||
m_textAntialiasBitsSpinBox->setRange(1, 2);
|
||||
m_textAntialiasBitsSpinBox->setValue(m_settings->value("textAntialiasBits", Defaults::textAntialiasBits).toInt());
|
||||
|
||||
m_layout->addRow(tr("Text antialias bits:"), m_textAntialiasBitsSpinBox);
|
||||
}
|
||||
|
||||
void PsSettingsWidget::accept()
|
||||
{
|
||||
m_settings->setValue("graphicsAntialiasBits", m_graphicsAntialiasBitsSpinBox->value());
|
||||
m_settings->setValue("textAntialiasBits", m_textAntialiasBitsSpinBox->value());
|
||||
}
|
||||
|
||||
void PsSettingsWidget::reset()
|
||||
{
|
||||
m_graphicsAntialiasBitsSpinBox->setValue(Defaults::graphicsAntialiasBits);
|
||||
m_textAntialiasBitsSpinBox->setValue(Defaults::textAntialiasBits);
|
||||
}
|
||||
|
||||
PsPlugin::PsPlugin(QObject* parent) : QObject(parent)
|
||||
{
|
||||
setObjectName("PsPlugin");
|
||||
|
||||
m_settings = new QSettings("qpdfview", "ps-plugin", this);
|
||||
}
|
||||
|
||||
Model::Document* PsPlugin::loadDocument(const QString& filePath) const
|
||||
{
|
||||
SpectreDocument* document = spectre_document_new();
|
||||
|
||||
spectre_document_load(document, QFile::encodeName(filePath));
|
||||
|
||||
if (spectre_document_status(document) != SPECTRE_STATUS_SUCCESS)
|
||||
{
|
||||
spectre_document_free(document);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SpectreRenderContext* renderContext = spectre_render_context_new();
|
||||
|
||||
spectre_render_context_set_antialias_bits(renderContext,
|
||||
m_settings->value("graphicsAntialiasBits", Defaults::graphicsAntialiasBits).toInt(),
|
||||
m_settings->value("textAntialiasBits", Defaults::textAntialiasBits).toInt());
|
||||
|
||||
return new Model::PsDocument(document, renderContext);
|
||||
}
|
||||
|
||||
SettingsWidget* PsPlugin::createSettingsWidget(QWidget* parent) const
|
||||
{
|
||||
return new PsSettingsWidget(m_settings, parent);
|
||||
}
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
Q_EXPORT_PLUGIN2(qpdfview_ps, qpdfview::PsPlugin)
|
||||
|
||||
#endif // QT_VERSION
|
151
sources/psmodel.h
Parasts fails
151
sources/psmodel.h
Parasts fails
@ -0,0 +1,151 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Alexander Volkov
|
||||
Copyright 2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PSMODEL_H
|
||||
#define PSMODEL_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QMutex>
|
||||
|
||||
class QFormLayout;
|
||||
class QSettings;
|
||||
class QSpinBox;
|
||||
|
||||
struct SpectrePage;
|
||||
struct SpectreDocument;
|
||||
struct SpectreRenderContext;
|
||||
|
||||
#include "model.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class PsPlugin;
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class PsPage : public Page
|
||||
{
|
||||
friend class PsDocument;
|
||||
|
||||
public:
|
||||
~PsPage();
|
||||
|
||||
QSizeF size() const;
|
||||
|
||||
QImage render(qreal horizontalResolution, qreal verticalResolution, Rotation rotation, QRect boundingRect) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PsPage)
|
||||
|
||||
PsPage(QMutex* mutex, SpectrePage* page, SpectreRenderContext* renderContext);
|
||||
|
||||
mutable QMutex* m_mutex;
|
||||
SpectrePage* m_page;
|
||||
SpectreRenderContext* m_renderContext;
|
||||
|
||||
};
|
||||
|
||||
class PsDocument : public Document
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Model::PsDocument)
|
||||
|
||||
friend class qpdfview::PsPlugin;
|
||||
|
||||
public:
|
||||
~PsDocument();
|
||||
|
||||
int numberOfPages() const;
|
||||
|
||||
Page* page(int index) const;
|
||||
|
||||
QStringList saveFilter() const;
|
||||
|
||||
bool canSave() const;
|
||||
bool save(const QString& filePath, bool withChanges) const;
|
||||
|
||||
bool canBePrintedUsingCUPS() const;
|
||||
|
||||
Properties properties() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PsDocument)
|
||||
|
||||
PsDocument(SpectreDocument* document, SpectreRenderContext* renderContext);
|
||||
|
||||
mutable QMutex m_mutex;
|
||||
SpectreDocument* m_document;
|
||||
SpectreRenderContext* m_renderContext;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
class PsSettingsWidget : public SettingsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PsSettingsWidget(QSettings* settings, QWidget* parent = 0);
|
||||
|
||||
void accept();
|
||||
void reset();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PsSettingsWidget)
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
QFormLayout* m_layout;
|
||||
|
||||
QSpinBox* m_graphicsAntialiasBitsSpinBox;
|
||||
QSpinBox* m_textAntialiasBitsSpinBox;
|
||||
|
||||
};
|
||||
|
||||
class PsPlugin : public QObject, Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(qpdfview::Plugin)
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
Q_PLUGIN_METADATA(IID "local.qpdfview.Plugin")
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
public:
|
||||
PsPlugin(QObject* parent = 0);
|
||||
|
||||
Model::Document* loadDocument(const QString& filePath) const;
|
||||
|
||||
SettingsWidget* createSettingsWidget(QWidget* parent) const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(PsPlugin)
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // PSMODEL_H
|
95
sources/recentlyclosedmenu.cpp
Parasts fails
95
sources/recentlyclosedmenu.cpp
Parasts fails
@ -0,0 +1,95 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "recentlyclosedmenu.h"
|
||||
|
||||
#include "documentview.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
RecentlyClosedMenu::RecentlyClosedMenu(int count, QWidget* parent) : ToolTipMenu(parent),
|
||||
m_count(count)
|
||||
{
|
||||
menuAction()->setText(tr("&Recently closed"));
|
||||
|
||||
m_tabActionGroup = new QActionGroup(this);
|
||||
connect(m_tabActionGroup, SIGNAL(triggered(QAction*)), SLOT(on_tabAction_triggered(QAction*)));
|
||||
|
||||
m_separatorAction = addSeparator();
|
||||
|
||||
m_clearListAction = addAction(tr("&Clear list"));
|
||||
connect(m_clearListAction, SIGNAL(triggered()), SLOT(on_clearList_triggered()));
|
||||
}
|
||||
|
||||
void RecentlyClosedMenu::addTabAction(QAction* tabAction)
|
||||
{
|
||||
if(m_tabActionGroup->actions().count() >= m_count)
|
||||
{
|
||||
QAction* first = m_tabActionGroup->actions().at(0);
|
||||
|
||||
removeAction(first);
|
||||
m_tabActionGroup->removeAction(first);
|
||||
|
||||
first->parent()->deleteLater();
|
||||
}
|
||||
|
||||
insertAction(actions().at(0), tabAction);
|
||||
m_tabActionGroup->addAction(tabAction);
|
||||
}
|
||||
|
||||
void RecentlyClosedMenu::triggerFirstTabAction()
|
||||
{
|
||||
const QList< QAction* >& actions = m_tabActionGroup->actions();
|
||||
|
||||
if(!actions.isEmpty())
|
||||
{
|
||||
on_tabAction_triggered(actions.first());
|
||||
}
|
||||
}
|
||||
|
||||
void RecentlyClosedMenu::triggerLastTabAction()
|
||||
{
|
||||
const QList< QAction* >& actions = m_tabActionGroup->actions();
|
||||
|
||||
if(!actions.isEmpty())
|
||||
{
|
||||
on_tabAction_triggered(actions.last());
|
||||
}
|
||||
}
|
||||
|
||||
void RecentlyClosedMenu::on_tabAction_triggered(QAction* tabAction)
|
||||
{
|
||||
removeAction(tabAction);
|
||||
m_tabActionGroup->removeAction(tabAction);
|
||||
|
||||
emit tabActionTriggered(tabAction);
|
||||
}
|
||||
|
||||
void RecentlyClosedMenu::on_clearList_triggered()
|
||||
{
|
||||
foreach(QAction* action, m_tabActionGroup->actions())
|
||||
{
|
||||
action->parent()->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
} // qpdfview
|
63
sources/recentlyclosedmenu.h
Parasts fails
63
sources/recentlyclosedmenu.h
Parasts fails
@ -0,0 +1,63 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RECENTLYCLOSEDMENU_H
|
||||
#define RECENTLYCLOSEDMENU_H
|
||||
|
||||
#include "miscellaneous.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class RecentlyClosedMenu : public ToolTipMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RecentlyClosedMenu(int count, QWidget *parent = 0);
|
||||
|
||||
void addTabAction(QAction* tabAction);
|
||||
|
||||
signals:
|
||||
void tabActionTriggered(QAction* tabAction);
|
||||
|
||||
public slots:
|
||||
void triggerFirstTabAction();
|
||||
void triggerLastTabAction();
|
||||
|
||||
protected slots:
|
||||
void on_tabAction_triggered(QAction* tabAction);
|
||||
void on_clearList_triggered();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(RecentlyClosedMenu)
|
||||
|
||||
int m_count;
|
||||
|
||||
QActionGroup* m_tabActionGroup;
|
||||
QAction* m_separatorAction;
|
||||
QAction* m_clearListAction;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // RECENTLYCLOSEDMENU_H
|
121
sources/recentlyusedmenu.cpp
Parasts fails
121
sources/recentlyusedmenu.cpp
Parasts fails
@ -0,0 +1,121 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "recentlyusedmenu.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
RecentlyUsedMenu::RecentlyUsedMenu(const QStringList& absoluteFilePaths, int count, QWidget* parent) : ToolTipMenu(parent),
|
||||
m_count(count)
|
||||
{
|
||||
menuAction()->setText(tr("Recently &used"));
|
||||
menuAction()->setIcon(QIcon::fromTheme("document-open-recent"));
|
||||
menuAction()->setIconVisibleInMenu(true);
|
||||
|
||||
m_openActionGroup = new QActionGroup(this);
|
||||
connect(m_openActionGroup, SIGNAL(triggered(QAction*)), SLOT(on_open_triggered(QAction*)));
|
||||
|
||||
m_separatorAction = addSeparator();
|
||||
|
||||
m_clearListAction = addAction(tr("&Clear list"));
|
||||
connect(m_clearListAction, SIGNAL(triggered()), SLOT(on_clearList_triggered()));
|
||||
|
||||
foreach(const QString& absoluteFilePath, absoluteFilePaths)
|
||||
{
|
||||
addOpenAction(QFileInfo(absoluteFilePath));
|
||||
}
|
||||
}
|
||||
|
||||
void RecentlyUsedMenu::addOpenAction(const QFileInfo& fileInfo)
|
||||
{
|
||||
foreach(QAction* action, m_openActionGroup->actions())
|
||||
{
|
||||
if(action->data().toString() == fileInfo.absoluteFilePath())
|
||||
{
|
||||
removeAction(action);
|
||||
m_openActionGroup->removeAction(action);
|
||||
|
||||
insertAction(actions().at(0), action);
|
||||
m_openActionGroup->addAction(action);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_openActionGroup->actions().count() >= m_count)
|
||||
{
|
||||
QAction* first = m_openActionGroup->actions().at(0);
|
||||
|
||||
removeAction(first);
|
||||
m_openActionGroup->removeAction(first);
|
||||
|
||||
delete first;
|
||||
}
|
||||
|
||||
QAction* action = new QAction(fileInfo.completeBaseName(), this);
|
||||
action->setToolTip(fileInfo.absoluteFilePath());
|
||||
action->setData(fileInfo.absoluteFilePath());
|
||||
|
||||
insertAction(actions().at(0), action);
|
||||
m_openActionGroup->addAction(action);
|
||||
}
|
||||
|
||||
void RecentlyUsedMenu::removeOpenAction(const QString& filePath)
|
||||
{
|
||||
const QFileInfo fileInfo(filePath);
|
||||
|
||||
foreach(QAction* action, m_openActionGroup->actions())
|
||||
{
|
||||
if(action->data().toString() == fileInfo.absoluteFilePath())
|
||||
{
|
||||
delete action;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStringList RecentlyUsedMenu::filePaths() const
|
||||
{
|
||||
QStringList filePaths;
|
||||
|
||||
foreach(const QAction* action, m_openActionGroup->actions())
|
||||
{
|
||||
filePaths.append(action->data().toString());
|
||||
}
|
||||
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
void RecentlyUsedMenu::on_open_triggered(QAction* action)
|
||||
{
|
||||
emit openTriggered(action->data().toString());
|
||||
}
|
||||
|
||||
void RecentlyUsedMenu::on_clearList_triggered()
|
||||
{
|
||||
qDeleteAll(m_openActionGroup->actions());
|
||||
}
|
||||
|
||||
} // qpdfview
|
64
sources/recentlyusedmenu.h
Parasts fails
64
sources/recentlyusedmenu.h
Parasts fails
@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RECENTLYUSEDMENU_H
|
||||
#define RECENTLYUSEDMENU_H
|
||||
|
||||
#include "miscellaneous.h"
|
||||
|
||||
class QFileInfo;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class RecentlyUsedMenu : public ToolTipMenu
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RecentlyUsedMenu(const QStringList& filePaths, int count, QWidget* parent = 0);
|
||||
|
||||
void addOpenAction(const QFileInfo& fileInfo);
|
||||
void removeOpenAction(const QString& filePath);
|
||||
|
||||
QStringList filePaths() const;
|
||||
|
||||
signals:
|
||||
void openTriggered(const QString& filePath);
|
||||
|
||||
protected slots:
|
||||
void on_open_triggered(QAction* action);
|
||||
void on_clearList_triggered();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(RecentlyUsedMenu)
|
||||
|
||||
int m_count;
|
||||
|
||||
QActionGroup* m_openActionGroup;
|
||||
QAction* m_separatorAction;
|
||||
QAction* m_clearListAction;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // RECENTLYUSEDMENU_H
|
156
sources/renderparam.h
Parasts fails
156
sources/renderparam.h
Parasts fails
@ -0,0 +1,156 @@
|
||||
/*
|
||||
|
||||
Copyright 2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RENDERPARAM_H
|
||||
#define RENDERPARAM_H
|
||||
|
||||
#include <QSharedDataPointer>
|
||||
|
||||
#include "global.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
enum RenderFlag
|
||||
{
|
||||
InvertColors = 1 << 0,
|
||||
ConvertToGrayscale = 1 << 1,
|
||||
TrimMargins = 1 << 2,
|
||||
DarkenWithPaperColor = 1 << 3,
|
||||
LightenWithPaperColor = 1 << 4
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(RenderFlags, RenderFlag)
|
||||
|
||||
class RenderParam
|
||||
{
|
||||
public:
|
||||
RenderParam(int resolutionX = 72, int resolutionY = 72, qreal devicePixelRatio = 1.0,
|
||||
qreal scaleFactor = 1.0, Rotation rotation = RotateBy0,
|
||||
RenderFlags flags = 0) : d(new SharedData)
|
||||
{
|
||||
d->resolutionX = resolutionX;
|
||||
d->resolutionY = resolutionY;
|
||||
d->devicePixelRatio = devicePixelRatio;
|
||||
d->scaleFactor = scaleFactor;
|
||||
d->rotation = rotation;
|
||||
d->flags = flags;
|
||||
}
|
||||
|
||||
int resolutionX() const { return d->resolutionX; }
|
||||
int resolutionY() const { return d->resolutionY; }
|
||||
void setResolution(int resolutionX, int resolutionY)
|
||||
{
|
||||
d->resolutionX = resolutionX;
|
||||
d->resolutionY = resolutionY;
|
||||
}
|
||||
|
||||
qreal devicePixelRatio() const { return d->devicePixelRatio; }
|
||||
void setDevicePixelRatio(qreal devicePixelRatio) { d->devicePixelRatio = devicePixelRatio; }
|
||||
|
||||
qreal scaleFactor() const { return d->scaleFactor; }
|
||||
void setScaleFactor(qreal scaleFactor) { d->scaleFactor = scaleFactor; }
|
||||
|
||||
Rotation rotation() const { return d->rotation; }
|
||||
void setRotation(Rotation rotation) { d->rotation = rotation; }
|
||||
|
||||
RenderFlags flags() const { return d->flags; }
|
||||
void setFlags(RenderFlags flags) { d->flags = flags; }
|
||||
void setFlag(RenderFlag flag, bool enabled = true)
|
||||
{
|
||||
if(enabled)
|
||||
{
|
||||
d->flags |= flag;
|
||||
}
|
||||
else
|
||||
{
|
||||
d->flags &= ~flag;
|
||||
}
|
||||
}
|
||||
|
||||
bool invertColors() const { return d->flags.testFlag(InvertColors); }
|
||||
void setInvertColors(bool invertColors) { setFlag(InvertColors, invertColors); }
|
||||
|
||||
bool convertToGrayscale() const { return d->flags.testFlag(ConvertToGrayscale); }
|
||||
void setConvertToGrayscale(bool convertToGrayscale) { setFlag(ConvertToGrayscale, convertToGrayscale); }
|
||||
|
||||
bool trimMargins() const { return d->flags.testFlag(TrimMargins); }
|
||||
void setTrimMargins(bool trimMargins) { setFlag(TrimMargins, trimMargins); }
|
||||
|
||||
bool darkenWithPaperColor() const { return d->flags.testFlag(DarkenWithPaperColor); }
|
||||
void setDarkenWithPaperColor(bool darkenWithPaperColor) { setFlag(DarkenWithPaperColor, darkenWithPaperColor); }
|
||||
|
||||
bool lightenWithPaperColor() const { return d->flags.testFlag(LightenWithPaperColor); }
|
||||
void setLightenWithPaperColor(bool lightenWithPaperColor) { setFlag(LightenWithPaperColor, lightenWithPaperColor); }
|
||||
|
||||
bool operator==(const RenderParam& other) const
|
||||
{
|
||||
if(d == other.d)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return d->resolutionX == other.d->resolutionX
|
||||
&& d->resolutionY == other.d->resolutionY
|
||||
&& qFuzzyCompare(d->devicePixelRatio, other.d->devicePixelRatio)
|
||||
&& qFuzzyCompare(d->scaleFactor, other.d->scaleFactor)
|
||||
&& d->rotation == other.d->rotation
|
||||
&& d->flags == other.d->flags;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator!=(const RenderParam& other) const { return !operator==(other); }
|
||||
|
||||
private:
|
||||
struct SharedData : public QSharedData
|
||||
{
|
||||
int resolutionX;
|
||||
int resolutionY;
|
||||
qreal devicePixelRatio;
|
||||
|
||||
qreal scaleFactor;
|
||||
Rotation rotation;
|
||||
|
||||
RenderFlags flags;
|
||||
|
||||
};
|
||||
|
||||
QSharedDataPointer< SharedData > d;
|
||||
|
||||
};
|
||||
|
||||
inline QDataStream& operator<<(QDataStream& stream, const RenderParam& that)
|
||||
{
|
||||
stream << that.resolutionX()
|
||||
<< that.resolutionY()
|
||||
<< that.devicePixelRatio()
|
||||
<< that.scaleFactor()
|
||||
<< that.rotation()
|
||||
<< that.flags();
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // RENDERPARAM_H
|
||||
|
542
sources/rendertask.cpp
Parasts fails
542
sources/rendertask.cpp
Parasts fails
@ -0,0 +1,542 @@
|
||||
/*
|
||||
|
||||
Copyright 2013-2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "rendertask.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <qmath.h>
|
||||
#include <QPainter>
|
||||
#include <QThreadPool>
|
||||
|
||||
#include "model.h"
|
||||
#include "settings.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void registerEventType(QEvent::Type& registeredType)
|
||||
{
|
||||
if(registeredType == QEvent::None)
|
||||
{
|
||||
registeredType = QEvent::Type(QEvent::registerEventType());
|
||||
}
|
||||
}
|
||||
|
||||
qreal scaledResolutionX(const RenderParam& renderParam)
|
||||
{
|
||||
return renderParam.devicePixelRatio()
|
||||
* renderParam.resolutionX()
|
||||
* renderParam.scaleFactor();
|
||||
}
|
||||
|
||||
qreal scaledResolutionY(const RenderParam& renderParam)
|
||||
{
|
||||
return renderParam.devicePixelRatio()
|
||||
* renderParam.resolutionY()
|
||||
* renderParam.scaleFactor();
|
||||
}
|
||||
|
||||
const QRgb alphaMask = 0xffu << 24;
|
||||
|
||||
bool columnHasPaperColor(int x, QRgb paperColor, const QImage& image)
|
||||
{
|
||||
const int height = image.height();
|
||||
|
||||
for(int y = 0; y < height; ++y)
|
||||
{
|
||||
const QRgb color = image.pixel(x, y);
|
||||
|
||||
if(qAlpha(color) != 0 && paperColor != (color | alphaMask))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rowHasPaperColor(int y, QRgb paperColor, const QImage& image)
|
||||
{
|
||||
const int width = image.width();
|
||||
|
||||
for(int x = 0; x < width; ++x)
|
||||
{
|
||||
const QRgb color = image.pixel(x, y);
|
||||
|
||||
if(qAlpha(color) != 0 && paperColor != (color | alphaMask))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QRectF trimMargins(QRgb paperColor, const QImage& image)
|
||||
{
|
||||
if(image.isNull())
|
||||
{
|
||||
return QRectF(0.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
const int width = image.width();
|
||||
const int height = image.height();
|
||||
|
||||
int left;
|
||||
for(left = 0; left < width; ++left)
|
||||
{
|
||||
if(!columnHasPaperColor(left, paperColor, image))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
left = qMin(left, width / 3);
|
||||
|
||||
int right;
|
||||
for(right = width - 1; right >= left; --right)
|
||||
{
|
||||
if(!columnHasPaperColor(right, paperColor, image))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
right = qMax(right, 2 * width / 3);
|
||||
|
||||
int top;
|
||||
for(top = 0; top < height; ++top)
|
||||
{
|
||||
if(!rowHasPaperColor(top, paperColor, image))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
top = qMin(top, height / 3);
|
||||
|
||||
int bottom;
|
||||
for(bottom = height - 1; bottom >= top; --bottom)
|
||||
{
|
||||
if(!rowHasPaperColor(bottom, paperColor, image))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
bottom = qMax(bottom, 2 * height / 3);
|
||||
|
||||
left = qMax(left - width / 100, 0);
|
||||
top = qMax(top - height / 100, 0);
|
||||
|
||||
right = qMin(right + width / 100, width);
|
||||
bottom = qMin(bottom + height / 100, height);
|
||||
|
||||
return QRectF(static_cast< qreal >(left) / width,
|
||||
static_cast< qreal >(top) / height,
|
||||
static_cast< qreal >(right - left) / width,
|
||||
static_cast< qreal >(bottom - top) / height);
|
||||
}
|
||||
|
||||
void convertToGrayscale(QImage& image)
|
||||
{
|
||||
QRgb* const begin = reinterpret_cast< QRgb* >(image.bits());
|
||||
QRgb* const end = reinterpret_cast< QRgb* >(image.bits() + image.byteCount());
|
||||
|
||||
for(QRgb* pointer = begin; pointer != end; ++pointer)
|
||||
{
|
||||
const int gray = qGray(*pointer);
|
||||
const int alpha = qAlpha(*pointer);
|
||||
|
||||
*pointer = qRgba(gray, gray, gray, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void composeWithColor(QPainter::CompositionMode mode, const QColor& color, QImage& image)
|
||||
{
|
||||
QPainter painter(&image);
|
||||
|
||||
painter.setCompositionMode(mode);
|
||||
painter.fillRect(image.rect(), color);
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
RenderTaskParent::~RenderTaskParent()
|
||||
{
|
||||
}
|
||||
|
||||
struct RenderTaskFinishedEvent : public QEvent
|
||||
{
|
||||
static QEvent::Type registeredType;
|
||||
|
||||
RenderTaskFinishedEvent(RenderTaskParent* const parent,
|
||||
const RenderParam& renderParam,
|
||||
const QRect& rect,
|
||||
const bool prefetch,
|
||||
const QImage& image,
|
||||
const QRectF& cropRect)
|
||||
: QEvent(registeredType)
|
||||
, parent(parent)
|
||||
, renderParam(renderParam)
|
||||
, rect(rect)
|
||||
, prefetch(prefetch)
|
||||
, image(image)
|
||||
, cropRect(cropRect)
|
||||
{
|
||||
}
|
||||
~RenderTaskFinishedEvent();
|
||||
|
||||
void dispatch() const
|
||||
{
|
||||
parent->on_finished(renderParam,
|
||||
rect, prefetch,
|
||||
image, cropRect);
|
||||
}
|
||||
|
||||
RenderTaskParent* const parent;
|
||||
|
||||
const RenderParam renderParam;
|
||||
const QRect rect;
|
||||
const bool prefetch;
|
||||
const QImage image;
|
||||
const QRectF cropRect;
|
||||
};
|
||||
|
||||
QEvent::Type RenderTaskFinishedEvent::registeredType = QEvent::None;
|
||||
|
||||
RenderTaskFinishedEvent::~RenderTaskFinishedEvent()
|
||||
{
|
||||
}
|
||||
|
||||
struct RenderTaskCanceledEvent : public QEvent
|
||||
{
|
||||
|
||||
static QEvent::Type registeredType;
|
||||
|
||||
RenderTaskCanceledEvent(RenderTaskParent* parent)
|
||||
: QEvent(registeredType)
|
||||
, parent(parent)
|
||||
{
|
||||
}
|
||||
~RenderTaskCanceledEvent();
|
||||
|
||||
void dispatch() const
|
||||
{
|
||||
parent->on_canceled();
|
||||
}
|
||||
|
||||
RenderTaskParent* const parent;
|
||||
};
|
||||
|
||||
QEvent::Type RenderTaskCanceledEvent::registeredType = QEvent::None;
|
||||
|
||||
RenderTaskCanceledEvent::~RenderTaskCanceledEvent()
|
||||
{
|
||||
}
|
||||
|
||||
struct DeleteParentLaterEvent : public QEvent
|
||||
{
|
||||
static QEvent::Type registeredType;
|
||||
|
||||
DeleteParentLaterEvent(RenderTaskParent* const parent)
|
||||
: QEvent(registeredType)
|
||||
, parent(parent)
|
||||
{
|
||||
}
|
||||
~DeleteParentLaterEvent();
|
||||
|
||||
void dispatch() const
|
||||
{
|
||||
delete parent;
|
||||
}
|
||||
|
||||
RenderTaskParent* const parent;
|
||||
};
|
||||
|
||||
QEvent::Type DeleteParentLaterEvent::registeredType = QEvent::None;
|
||||
|
||||
DeleteParentLaterEvent::~DeleteParentLaterEvent()
|
||||
{
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class DispatchChain
|
||||
{
|
||||
public:
|
||||
DispatchChain(const QEvent* const event, const QSet< RenderTaskParent* >& activeParents) :
|
||||
m_event(event),
|
||||
m_activeParents(activeParents)
|
||||
{
|
||||
}
|
||||
|
||||
template< typename Event >
|
||||
DispatchChain& dispatch()
|
||||
{
|
||||
if(m_event != 0 && m_event->type() == Event::registeredType)
|
||||
{
|
||||
const Event* const event = static_cast< const Event* >(m_event);
|
||||
|
||||
m_event = 0;
|
||||
|
||||
if(m_activeParents.contains(event->parent))
|
||||
{
|
||||
event->dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool wasDispatched() const
|
||||
{
|
||||
return m_event == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const QEvent* m_event;
|
||||
const QSet< RenderTaskParent* >& m_activeParents;
|
||||
};
|
||||
|
||||
} // anonymous
|
||||
|
||||
RenderTaskDispatcher::RenderTaskDispatcher(QObject* parent) : QObject(parent)
|
||||
{
|
||||
registerEventType(DeleteParentLaterEvent::registeredType);
|
||||
registerEventType(RenderTaskFinishedEvent::registeredType);
|
||||
registerEventType(RenderTaskCanceledEvent::registeredType);
|
||||
}
|
||||
|
||||
void RenderTaskDispatcher::finished(RenderTaskParent* parent,
|
||||
const RenderParam& renderParam,
|
||||
const QRect& rect, bool prefetch,
|
||||
const QImage& image, const QRectF& cropRect)
|
||||
{
|
||||
RenderTaskFinishedEvent* const event = new RenderTaskFinishedEvent(parent,
|
||||
renderParam,
|
||||
rect, prefetch,
|
||||
image, cropRect);
|
||||
|
||||
QApplication::postEvent(this, event, Qt::HighEventPriority);
|
||||
}
|
||||
|
||||
void RenderTaskDispatcher::canceled(RenderTaskParent* parent)
|
||||
{
|
||||
QApplication::postEvent(this, new RenderTaskCanceledEvent(parent), Qt::HighEventPriority);
|
||||
}
|
||||
|
||||
void RenderTaskDispatcher::deleteParentLater(RenderTaskParent* parent)
|
||||
{
|
||||
QApplication::postEvent(this, new DeleteParentLaterEvent(parent), Qt::LowEventPriority);
|
||||
}
|
||||
|
||||
bool RenderTaskDispatcher::event(QEvent* event)
|
||||
{
|
||||
DispatchChain chain(event, m_activeParents);
|
||||
|
||||
chain.dispatch< RenderTaskFinishedEvent >()
|
||||
.dispatch< RenderTaskCanceledEvent >()
|
||||
.dispatch< DeleteParentLaterEvent >();
|
||||
|
||||
return chain.wasDispatched() || QObject::event(event);
|
||||
}
|
||||
|
||||
void RenderTaskDispatcher::addActiveParent(RenderTaskParent* parent)
|
||||
{
|
||||
m_activeParents.insert(parent);
|
||||
}
|
||||
|
||||
void RenderTaskDispatcher::removeActiveParent(RenderTaskParent* parent)
|
||||
{
|
||||
m_activeParents.remove(parent);
|
||||
}
|
||||
|
||||
RenderTaskDispatcher* RenderTask::s_dispatcher = 0;
|
||||
|
||||
Settings* RenderTask::s_settings = 0;
|
||||
|
||||
const RenderParam RenderTask::s_defaultRenderParam;
|
||||
|
||||
RenderTask::RenderTask(Model::Page* page, RenderTaskParent* parent) : QRunnable(),
|
||||
m_parent(parent),
|
||||
m_isRunning(false),
|
||||
m_wasCanceled(NotCanceled),
|
||||
m_page(page),
|
||||
m_renderParam(s_defaultRenderParam),
|
||||
m_rect(),
|
||||
m_prefetch(false)
|
||||
{
|
||||
if(s_settings == 0)
|
||||
{
|
||||
s_settings = Settings::instance();
|
||||
}
|
||||
|
||||
if(s_dispatcher == 0)
|
||||
{
|
||||
s_dispatcher = new RenderTaskDispatcher(qApp);
|
||||
}
|
||||
|
||||
setAutoDelete(false);
|
||||
|
||||
s_dispatcher->addActiveParent(m_parent);
|
||||
}
|
||||
|
||||
RenderTask::~RenderTask()
|
||||
{
|
||||
s_dispatcher->removeActiveParent(m_parent);
|
||||
}
|
||||
|
||||
void RenderTask::wait()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
while(m_isRunning)
|
||||
{
|
||||
m_waitCondition.wait(&m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderTask::isRunning() const
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
return m_isRunning;
|
||||
}
|
||||
|
||||
void RenderTask::run()
|
||||
{
|
||||
#define CANCELLATION_POINT if(testCancellation()) { finish(true); return; }
|
||||
|
||||
CANCELLATION_POINT
|
||||
|
||||
QImage image;
|
||||
QRectF cropRect;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,1,0)
|
||||
|
||||
const qreal devicePixelRatio = m_renderParam.devicePixelRatio();
|
||||
|
||||
const QRect rect =
|
||||
qFuzzyCompare(1.0, devicePixelRatio)
|
||||
? m_rect
|
||||
: QTransform().scale(devicePixelRatio, devicePixelRatio).mapRect(m_rect);
|
||||
|
||||
#else
|
||||
|
||||
const QRect& rect = m_rect;
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
image = m_page->render(scaledResolutionX(m_renderParam), scaledResolutionY(m_renderParam),
|
||||
m_renderParam.rotation(), rect);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,1,0)
|
||||
|
||||
image.setDevicePixelRatio(devicePixelRatio);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
if(m_renderParam.darkenWithPaperColor())
|
||||
{
|
||||
CANCELLATION_POINT
|
||||
|
||||
composeWithColor(QPainter::CompositionMode_Darken, s_settings->pageItem().paperColor(), image);
|
||||
}
|
||||
else if(m_renderParam.lightenWithPaperColor())
|
||||
{
|
||||
CANCELLATION_POINT
|
||||
|
||||
composeWithColor(QPainter::CompositionMode_Lighten, s_settings->pageItem().paperColor(), image);
|
||||
}
|
||||
|
||||
if(m_renderParam.trimMargins())
|
||||
{
|
||||
CANCELLATION_POINT
|
||||
|
||||
cropRect = trimMargins(s_settings->pageItem().paperColor().rgb() | alphaMask, image);
|
||||
}
|
||||
|
||||
if(m_renderParam.convertToGrayscale())
|
||||
{
|
||||
CANCELLATION_POINT
|
||||
|
||||
convertToGrayscale(image);
|
||||
}
|
||||
|
||||
if(m_renderParam.invertColors())
|
||||
{
|
||||
CANCELLATION_POINT
|
||||
|
||||
image.invertPixels();
|
||||
}
|
||||
|
||||
CANCELLATION_POINT
|
||||
|
||||
s_dispatcher->finished(m_parent,
|
||||
m_renderParam,
|
||||
m_rect, m_prefetch,
|
||||
image, cropRect);
|
||||
|
||||
finish(false);
|
||||
|
||||
#undef CANCELLATION_POINT
|
||||
}
|
||||
|
||||
void RenderTask::start(const RenderParam& renderParam,
|
||||
const QRect& rect, bool prefetch)
|
||||
{
|
||||
m_renderParam = renderParam;
|
||||
|
||||
m_rect = rect;
|
||||
m_prefetch = prefetch;
|
||||
|
||||
m_mutex.lock();
|
||||
m_isRunning = true;
|
||||
m_mutex.unlock();
|
||||
|
||||
resetCancellation();
|
||||
|
||||
QThreadPool::globalInstance()->start(this, prefetch ? 1 : 2);
|
||||
}
|
||||
|
||||
void RenderTask::deleteParentLater()
|
||||
{
|
||||
s_dispatcher->deleteParentLater(m_parent);
|
||||
}
|
||||
|
||||
void RenderTask::finish(bool canceled)
|
||||
{
|
||||
m_renderParam = s_defaultRenderParam;
|
||||
|
||||
if(canceled)
|
||||
{
|
||||
s_dispatcher->canceled(m_parent);
|
||||
}
|
||||
|
||||
m_mutex.lock();
|
||||
m_isRunning = false;
|
||||
m_mutex.unlock();
|
||||
|
||||
m_waitCondition.wakeAll();
|
||||
}
|
||||
|
||||
} // qpdfview
|
204
sources/rendertask.h
Parasts fails
204
sources/rendertask.h
Parasts fails
@ -0,0 +1,204 @@
|
||||
/*
|
||||
|
||||
Copyright 2013-2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef RENDERTASK_H
|
||||
#define RENDERTASK_H
|
||||
|
||||
#include <QImage>
|
||||
#include <QMutex>
|
||||
#include <QRunnable>
|
||||
#include <QSet>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include "renderparam.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class Page;
|
||||
}
|
||||
|
||||
class Settings;
|
||||
|
||||
class RenderTaskParent
|
||||
{
|
||||
friend struct RenderTaskFinishedEvent;
|
||||
friend struct RenderTaskCanceledEvent;
|
||||
friend struct DeleteParentLaterEvent;
|
||||
|
||||
public:
|
||||
virtual ~RenderTaskParent();
|
||||
|
||||
private:
|
||||
virtual void on_finished(const RenderParam& renderParam,
|
||||
const QRect& rect, bool prefetch,
|
||||
const QImage& image, const QRectF& cropRect) = 0;
|
||||
virtual void on_canceled() = 0;
|
||||
};
|
||||
|
||||
class RenderTaskDispatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class RenderTask;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(RenderTaskDispatcher)
|
||||
|
||||
RenderTaskDispatcher(QObject* parent = 0);
|
||||
|
||||
|
||||
void finished(RenderTaskParent* parent,
|
||||
const RenderParam& renderParam,
|
||||
const QRect& rect, bool prefetch,
|
||||
const QImage& image, const QRectF& cropRect);
|
||||
void canceled(RenderTaskParent* parent);
|
||||
|
||||
void deleteParentLater(RenderTaskParent* parent);
|
||||
|
||||
public:
|
||||
bool event(QEvent* event);
|
||||
|
||||
private:
|
||||
QSet< RenderTaskParent* > m_activeParents;
|
||||
|
||||
void addActiveParent(RenderTaskParent* parent);
|
||||
void removeActiveParent(RenderTaskParent* parent);
|
||||
|
||||
};
|
||||
|
||||
class RenderTask : public QRunnable
|
||||
{
|
||||
public:
|
||||
explicit RenderTask(Model::Page* page, RenderTaskParent* parent = 0);
|
||||
~RenderTask();
|
||||
|
||||
void wait();
|
||||
|
||||
bool isRunning() const;
|
||||
|
||||
bool wasCanceled() const { return loadCancellation() != NotCanceled; }
|
||||
bool wasCanceledNormally() const { return loadCancellation() == CanceledNormally; }
|
||||
bool wasCanceledForcibly() const { return loadCancellation() == CanceledForcibly; }
|
||||
|
||||
void run();
|
||||
|
||||
void start(const RenderParam& renderParam,
|
||||
const QRect& rect, bool prefetch);
|
||||
|
||||
void cancel(bool force = false) { setCancellation(force); }
|
||||
|
||||
void deleteParentLater();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(RenderTask)
|
||||
|
||||
static Settings* s_settings;
|
||||
|
||||
static RenderTaskDispatcher* s_dispatcher;
|
||||
RenderTaskParent* m_parent;
|
||||
|
||||
mutable QMutex m_mutex;
|
||||
QWaitCondition m_waitCondition;
|
||||
|
||||
bool m_isRunning;
|
||||
QAtomicInt m_wasCanceled;
|
||||
|
||||
enum
|
||||
{
|
||||
NotCanceled = 0,
|
||||
CanceledNormally = 1,
|
||||
CanceledForcibly = 2
|
||||
};
|
||||
|
||||
void setCancellation(bool force);
|
||||
void resetCancellation();
|
||||
bool testCancellation();
|
||||
int loadCancellation() const;
|
||||
|
||||
void finish(bool canceled);
|
||||
|
||||
|
||||
Model::Page* m_page;
|
||||
|
||||
static const RenderParam s_defaultRenderParam;
|
||||
RenderParam m_renderParam;
|
||||
|
||||
QRect m_rect;
|
||||
bool m_prefetch;
|
||||
|
||||
};
|
||||
|
||||
#if QT_VERSION > QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
inline void RenderTask::setCancellation(bool force)
|
||||
{
|
||||
m_wasCanceled.storeRelease(force ? CanceledForcibly : CanceledNormally);
|
||||
}
|
||||
|
||||
inline void RenderTask::resetCancellation()
|
||||
{
|
||||
m_wasCanceled.storeRelease(NotCanceled);
|
||||
}
|
||||
|
||||
inline bool RenderTask::testCancellation()
|
||||
{
|
||||
return m_prefetch ?
|
||||
m_wasCanceled.load() == CanceledForcibly :
|
||||
m_wasCanceled.load() != NotCanceled;
|
||||
}
|
||||
|
||||
inline int RenderTask::loadCancellation() const
|
||||
{
|
||||
return m_wasCanceled.load();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void RenderTask::setCancellation(bool force)
|
||||
{
|
||||
m_wasCanceled.fetchAndStoreRelease(force ? CanceledForcibly : CanceledNormally);
|
||||
}
|
||||
|
||||
inline void RenderTask::resetCancellation()
|
||||
{
|
||||
m_wasCanceled.fetchAndStoreRelease(NotCanceled);
|
||||
}
|
||||
|
||||
inline bool RenderTask::testCancellation()
|
||||
{
|
||||
return m_prefetch ?
|
||||
m_wasCanceled.testAndSetRelaxed(CanceledForcibly, CanceledForcibly) :
|
||||
!m_wasCanceled.testAndSetRelaxed(NotCanceled, NotCanceled);
|
||||
}
|
||||
|
||||
inline int RenderTask::loadCancellation() const
|
||||
{
|
||||
return m_wasCanceled;
|
||||
}
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // RENDERTASK_H
|
144
sources/searchitemdelegate.cpp
Parasts fails
144
sources/searchitemdelegate.cpp
Parasts fails
@ -0,0 +1,144 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 S. Razi Alavizadeh
|
||||
Copyright 2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "searchitemdelegate.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <qmath.h>
|
||||
#include <QPainter>
|
||||
#include <QTextLayout>
|
||||
|
||||
#include "searchmodel.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
SearchItemDelegate::SearchItemDelegate(QObject* parent) : QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void SearchItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
if(index.column() != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int progress = index.data(SearchModel::ProgressRole).toInt();
|
||||
|
||||
if(progress != 0)
|
||||
{
|
||||
paintProgress(painter, option, progress);
|
||||
return;
|
||||
}
|
||||
|
||||
const QString matchedText = index.data(SearchModel::MatchedTextRole).toString();
|
||||
const QString surroundingText = index.data(SearchModel::SurroundingTextRole).toString();
|
||||
|
||||
if(!matchedText.isEmpty() && !surroundingText.isEmpty())
|
||||
{
|
||||
paintText(painter, option, matchedText, surroundingText);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SearchItemDelegate::paintProgress(QPainter* painter, const QStyleOptionViewItem& option,
|
||||
int progress) const
|
||||
{
|
||||
QRect highlightedRect = option.rect;
|
||||
highlightedRect.setWidth(progress * highlightedRect.width() / 100);
|
||||
|
||||
painter->save();
|
||||
|
||||
painter->setCompositionMode(QPainter::CompositionMode_Multiply);
|
||||
painter->fillRect(highlightedRect, option.palette.highlight());
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void SearchItemDelegate::paintText(QPainter* painter, const QStyleOptionViewItem& option,
|
||||
const QString& matchedText, const QString& surroundingText) const
|
||||
{
|
||||
const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
|
||||
const QRect textRect = option.rect.adjusted(textMargin, 0, -textMargin, 0);
|
||||
const QString elidedText = option.fontMetrics.elidedText(surroundingText, option.textElideMode, textRect.width());
|
||||
|
||||
QTextOption textOption;
|
||||
textOption.setWrapMode(QTextOption::NoWrap);
|
||||
textOption.setTextDirection(elidedText.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight);
|
||||
textOption.setAlignment(QStyle::visualAlignment(textOption.textDirection(), option.displayAlignment));
|
||||
|
||||
QTextLayout textLayout;
|
||||
textLayout.setTextOption(textOption);
|
||||
textLayout.setText(elidedText);
|
||||
textLayout.setFont(option.font);
|
||||
|
||||
QFont font = textLayout.font();
|
||||
font.setWeight(QFont::Light);
|
||||
textLayout.setFont(font);
|
||||
|
||||
|
||||
QList< QTextLayout::FormatRange > additionalFormats;
|
||||
|
||||
for(int index = 0; (index = surroundingText.indexOf(matchedText, index)) != -1; index += matchedText.length())
|
||||
{
|
||||
QTextLayout::FormatRange formatRange;
|
||||
formatRange.start = index;
|
||||
formatRange.length = matchedText.length();
|
||||
formatRange.format.setFontWeight(QFont::Bold);
|
||||
|
||||
additionalFormats.append(formatRange);
|
||||
}
|
||||
|
||||
textLayout.setAdditionalFormats(additionalFormats);
|
||||
|
||||
|
||||
textLayout.beginLayout();
|
||||
|
||||
QTextLine textLine = textLayout.createLine();
|
||||
|
||||
if(!textLine.isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
textLine.setLineWidth(textRect.width());
|
||||
|
||||
textLayout.endLayout();
|
||||
|
||||
|
||||
const QSize layoutSize(textRect.width(), qFloor(textLine.height()));
|
||||
const QRect layoutRect = QStyle::alignedRect(option.direction, option.displayAlignment, layoutSize, textRect);
|
||||
|
||||
painter->save();
|
||||
|
||||
painter->setClipping(true);
|
||||
painter->setClipRect(layoutRect);
|
||||
|
||||
textLine.draw(painter, layoutRect.topLeft());
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
} // qpdfview
|
49
sources/searchitemdelegate.h
Parasts fails
49
sources/searchitemdelegate.h
Parasts fails
@ -0,0 +1,49 @@
|
||||
/*
|
||||
|
||||
Copyright 2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEARCHITEMDELEGATE_H
|
||||
#define SEARCHITEMDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class SearchItemDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SearchItemDelegate(QObject* parent = 0);
|
||||
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
|
||||
private:
|
||||
void paintProgress(QPainter* painter, const QStyleOptionViewItem& option,
|
||||
int progress) const;
|
||||
void paintText(QPainter* painter, const QStyleOptionViewItem& option,
|
||||
const QString& matchedText, const QString& surroundingText) const;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // SEARCHITEMDELEGATE_H
|
511
sources/searchmodel.cpp
Parasts fails
511
sources/searchmodel.cpp
Parasts fails
@ -0,0 +1,511 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2014-2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "searchmodel.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
#include "documentview.h"
|
||||
|
||||
static inline bool operator<(int page, const QPair< int, QRectF >& result) { return page < result.first; }
|
||||
static inline bool operator<(const QPair< int, QRectF >& result, int page) { return result.first < page; }
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
SearchModel* SearchModel::s_instance = 0;
|
||||
|
||||
SearchModel* SearchModel::instance()
|
||||
{
|
||||
if(s_instance == 0)
|
||||
{
|
||||
s_instance = new SearchModel(qApp);
|
||||
}
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
SearchModel::~SearchModel()
|
||||
{
|
||||
foreach(TextWatcher* watcher, m_textWatchers)
|
||||
{
|
||||
watcher->waitForFinished();
|
||||
watcher->deleteLater();
|
||||
}
|
||||
|
||||
qDeleteAll(m_results);
|
||||
|
||||
s_instance = 0;
|
||||
}
|
||||
|
||||
QModelIndex SearchModel::index(int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
if(hasIndex(row, column, parent))
|
||||
{
|
||||
if(!parent.isValid())
|
||||
{
|
||||
return createIndex(row, column);
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentView* view = m_views.value(parent.row(), 0);
|
||||
|
||||
return createIndex(row, column, view);
|
||||
}
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex SearchModel::parent(const QModelIndex& child) const
|
||||
{
|
||||
if(child.internalPointer() != 0)
|
||||
{
|
||||
DocumentView* view = static_cast< DocumentView* >(child.internalPointer());
|
||||
|
||||
return findView(view);
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
int SearchModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
if(!parent.isValid())
|
||||
{
|
||||
return m_views.count();
|
||||
}
|
||||
else if(parent.internalPointer() == 0)
|
||||
{
|
||||
DocumentView* view = m_views.value(parent.row(), 0);
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
if(results != 0)
|
||||
{
|
||||
return results->count();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SearchModel::columnCount(const QModelIndex&) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
QVariant SearchModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if(index.internalPointer() == 0)
|
||||
{
|
||||
DocumentView* view = m_views.value(index.row(), 0);
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
if(results == 0)
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
switch(role)
|
||||
{
|
||||
default:
|
||||
return QVariant();
|
||||
case CountRole:
|
||||
return results->count();
|
||||
case ProgressRole:
|
||||
return view->searchProgress();
|
||||
case Qt::DisplayRole:
|
||||
switch(index.column())
|
||||
{
|
||||
case 0:
|
||||
return view->title();
|
||||
case 1:
|
||||
return results->count();
|
||||
}
|
||||
case Qt::ToolTipRole:
|
||||
return tr("<b>%1</b> occurrences").arg(results->count());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentView* view = static_cast< DocumentView* >(index.internalPointer());
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
if(results == 0 || index.row() >= results->count())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const Result& result = results->at(index.row());
|
||||
|
||||
switch(role)
|
||||
{
|
||||
default:
|
||||
return QVariant();
|
||||
case PageRole:
|
||||
return result.first;
|
||||
case RectRole:
|
||||
return result.second;
|
||||
case TextRole:
|
||||
return view->searchText();
|
||||
case MatchCaseRole:
|
||||
return view->searchMatchCase();
|
||||
case WholeWordsRole:
|
||||
return view->searchWholeWords();
|
||||
case MatchedTextRole:
|
||||
return fetchMatchedText(view, result);
|
||||
case SurroundingTextRole:
|
||||
return fetchSurroundingText(view, result);
|
||||
case Qt::DisplayRole:
|
||||
switch(index.column())
|
||||
{
|
||||
case 0:
|
||||
return QVariant();
|
||||
case 1:
|
||||
return result.first;
|
||||
}
|
||||
case Qt::ToolTipRole:
|
||||
return tr("<b>%1</b> occurrences on page <b>%2</b>").arg(numberOfResultsOnPage(view, result.first)).arg(result.first);
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
DocumentView* SearchModel::viewForIndex(const QModelIndex& index) const
|
||||
{
|
||||
if(index.internalPointer() == 0)
|
||||
{
|
||||
return m_views.value(index.row(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast< DocumentView* >(index.internalPointer());
|
||||
}
|
||||
}
|
||||
|
||||
bool SearchModel::hasResults(DocumentView* view) const
|
||||
{
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
return results != 0 && !results->isEmpty();
|
||||
}
|
||||
|
||||
bool SearchModel::hasResultsOnPage(DocumentView* view, int page) const
|
||||
{
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
return results != 0 && qBinaryFind(results->begin(), results->end(), page) != results->end();
|
||||
}
|
||||
|
||||
int SearchModel::numberOfResultsOnPage(DocumentView* view, int page) const
|
||||
{
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
if(results == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Results::const_iterator pageBegin = qLowerBound(results->constBegin(), results->constEnd(), page);
|
||||
const Results::const_iterator pageEnd = qUpperBound(pageBegin, results->constEnd(), page);
|
||||
|
||||
return pageEnd - pageBegin;
|
||||
}
|
||||
|
||||
QList< QRectF > SearchModel::resultsOnPage(DocumentView* view, int page) const
|
||||
{
|
||||
QList< QRectF > resultsOnPage;
|
||||
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
if(results != 0)
|
||||
{
|
||||
const Results::const_iterator pageBegin = qLowerBound(results->constBegin(), results->constEnd(), page);
|
||||
const Results::const_iterator pageEnd = qUpperBound(pageBegin, results->constEnd(), page);
|
||||
|
||||
for(Results::const_iterator iterator = pageBegin; iterator != pageEnd; ++iterator)
|
||||
{
|
||||
resultsOnPage.append(iterator->second);
|
||||
}
|
||||
}
|
||||
|
||||
return resultsOnPage;
|
||||
}
|
||||
|
||||
QPersistentModelIndex SearchModel::findResult(DocumentView* view, const QPersistentModelIndex& currentResult, int currentPage, FindDirection direction) const
|
||||
{
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
if(results == 0 || results->isEmpty())
|
||||
{
|
||||
return QPersistentModelIndex();
|
||||
}
|
||||
|
||||
const int rows = results->count();
|
||||
int row;
|
||||
|
||||
if(currentResult.isValid())
|
||||
{
|
||||
switch(direction)
|
||||
{
|
||||
default:
|
||||
case FindNext:
|
||||
row = (currentResult.row() + 1) % rows;
|
||||
break;
|
||||
case FindPrevious:
|
||||
row = (currentResult.row() + rows - 1) % rows;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(direction)
|
||||
{
|
||||
default:
|
||||
case FindNext:
|
||||
{
|
||||
Results::const_iterator lowerBound = qLowerBound(results->constBegin(), results->constEnd(), currentPage);
|
||||
|
||||
row = (lowerBound - results->constBegin()) % rows;
|
||||
break;
|
||||
}
|
||||
case FindPrevious:
|
||||
{
|
||||
Results::const_iterator upperBound = qUpperBound(results->constBegin(), results->constEnd(), currentPage);
|
||||
|
||||
row = ((upperBound - results->constBegin()) + rows - 1) % rows;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return createIndex(row, 0, view);
|
||||
}
|
||||
|
||||
void SearchModel::insertResults(DocumentView* view, int page, const QList< QRectF >& resultsOnPage)
|
||||
{
|
||||
if(resultsOnPage.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QModelIndex parent = findOrInsertView(view);
|
||||
|
||||
Results* results = m_results.value(view);
|
||||
|
||||
Results::iterator at = qLowerBound(results->begin(), results->end(), page);
|
||||
const int row = at - results->begin();
|
||||
|
||||
beginInsertRows(parent, row, row + resultsOnPage.size() - 1);
|
||||
|
||||
for(int index = resultsOnPage.size() - 1; index >= 0; --index)
|
||||
{
|
||||
at = results->insert(at, qMakePair(page, resultsOnPage.at(index)));
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void SearchModel::clearResults(DocumentView* view)
|
||||
{
|
||||
typedef QHash< TextCacheKey, TextWatcher* >::iterator WatcherIterator;
|
||||
|
||||
for(WatcherIterator iterator = m_textWatchers.begin(); iterator != m_textWatchers.end(); ++iterator)
|
||||
{
|
||||
const TextCacheKey& key = iterator.key();
|
||||
|
||||
if(key.first == view)
|
||||
{
|
||||
TextWatcher* const watcher = iterator.value();
|
||||
watcher->cancel();
|
||||
watcher->waitForFinished();
|
||||
watcher->deleteLater();
|
||||
|
||||
iterator = m_textWatchers.erase(iterator);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(const TextCacheKey& key, m_textCache.keys())
|
||||
{
|
||||
if(key.first == view)
|
||||
{
|
||||
m_textCache.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
const QVector< DocumentView* >::iterator at = qBinaryFind(m_views.begin(), m_views.end(), view);
|
||||
const int row = at - m_views.begin();
|
||||
|
||||
if(at == m_views.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
|
||||
m_views.erase(at);
|
||||
delete m_results.take(view);
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void SearchModel::updateProgress(DocumentView* view)
|
||||
{
|
||||
QModelIndex index = findView(view);
|
||||
|
||||
if(index.isValid())
|
||||
{
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
}
|
||||
|
||||
void SearchModel::on_fetchSurroundingText_finished()
|
||||
{
|
||||
TextWatcher* watcher = dynamic_cast< TextWatcher* >(sender());
|
||||
|
||||
if(watcher == 0 || watcher->isCanceled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const TextJob job = watcher->result();
|
||||
|
||||
m_textWatchers.remove(job.key);
|
||||
watcher->deleteLater();
|
||||
|
||||
DocumentView* view = job.key.first;
|
||||
const Results* results = m_results.value(view, 0);
|
||||
|
||||
if(results == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int cost = job.object->first.length() + job.object->second.length();
|
||||
|
||||
m_textCache.insert(job.key, job.object, cost);
|
||||
|
||||
emit dataChanged(createIndex(0, 0, view), createIndex(results->count() - 1, 0, view));
|
||||
}
|
||||
|
||||
SearchModel::SearchModel(QObject* parent) : QAbstractItemModel(parent),
|
||||
m_views(),
|
||||
m_results(),
|
||||
m_textCache(1 << 16),
|
||||
m_textWatchers()
|
||||
{
|
||||
}
|
||||
|
||||
QModelIndex SearchModel::findView(DocumentView *view) const
|
||||
{
|
||||
const QVector< DocumentView* >::const_iterator at = qBinaryFind(m_views.constBegin(), m_views.constEnd(), view);
|
||||
const int row = at - m_views.constBegin();
|
||||
|
||||
if(at == m_views.constEnd())
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
return createIndex(row, 0);
|
||||
}
|
||||
|
||||
QModelIndex SearchModel::findOrInsertView(DocumentView* view)
|
||||
{
|
||||
const QVector< DocumentView* >::iterator at = qLowerBound(m_views.begin(), m_views.end(), view);
|
||||
const int row = at - m_views.begin();
|
||||
|
||||
if(at == m_views.end() || *at != view)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), row, row);
|
||||
|
||||
m_views.insert(at, view);
|
||||
m_results.insert(view, new Results);
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
return createIndex(row, 0);
|
||||
}
|
||||
|
||||
QString SearchModel::fetchMatchedText(DocumentView* view, const SearchModel::Result& result) const
|
||||
{
|
||||
const TextCacheObject* object = fetchText(view, result);
|
||||
|
||||
return object != 0 ? object->first : QString();
|
||||
}
|
||||
|
||||
QString SearchModel::fetchSurroundingText(DocumentView* view, const Result& result) const
|
||||
{
|
||||
const TextCacheObject* object = fetchText(view, result);
|
||||
|
||||
return object != 0 ? object->second : QString();
|
||||
}
|
||||
|
||||
const SearchModel::TextCacheObject* SearchModel::fetchText(DocumentView* view, const SearchModel::Result& result) const
|
||||
{
|
||||
const TextCacheKey key = textCacheKey(view, result);
|
||||
|
||||
if(const TextCacheObject* object = m_textCache.object(key))
|
||||
{
|
||||
return object;
|
||||
}
|
||||
|
||||
if(m_textWatchers.size() < 20 && !m_textWatchers.contains(key))
|
||||
{
|
||||
TextWatcher* watcher = new TextWatcher();
|
||||
m_textWatchers.insert(key, watcher);
|
||||
|
||||
connect(watcher, SIGNAL(finished()), SLOT(on_fetchSurroundingText_finished()));
|
||||
|
||||
watcher->setFuture(QtConcurrent::run(textJob, key, result));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline SearchModel::TextCacheKey SearchModel::textCacheKey(DocumentView* view, const Result& result)
|
||||
{
|
||||
QByteArray key;
|
||||
|
||||
QDataStream(&key, QIODevice::WriteOnly)
|
||||
<< result.first
|
||||
<< result.second;
|
||||
|
||||
return qMakePair(view, key);
|
||||
}
|
||||
|
||||
SearchModel::TextJob SearchModel::textJob(const TextCacheKey& key, const Result& result)
|
||||
{
|
||||
const QPair< QString, QString >& text = key.first->searchContext(result.first, result.second);
|
||||
|
||||
return TextJob(key, new TextCacheObject(text));
|
||||
}
|
||||
|
||||
} // qpdfview
|
140
sources/searchmodel.h
Parasts fails
140
sources/searchmodel.h
Parasts fails
@ -0,0 +1,140 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 S. Razi Alavizadeh
|
||||
Copyright 2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEARCHMODEL_H
|
||||
#define SEARCHMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QCache>
|
||||
#include <QFutureWatcher>
|
||||
#include <QRectF>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class DocumentView;
|
||||
|
||||
class SearchModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static SearchModel* instance();
|
||||
~SearchModel();
|
||||
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
|
||||
|
||||
QModelIndex parent(const QModelIndex& child) const;
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const;
|
||||
|
||||
enum
|
||||
{
|
||||
CountRole = Qt::UserRole + 1,
|
||||
ProgressRole,
|
||||
PageRole,
|
||||
RectRole,
|
||||
TextRole,
|
||||
MatchCaseRole,
|
||||
WholeWordsRole,
|
||||
MatchedTextRole,
|
||||
SurroundingTextRole
|
||||
};
|
||||
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||
|
||||
|
||||
DocumentView* viewForIndex(const QModelIndex& index) const;
|
||||
|
||||
|
||||
bool hasResults(DocumentView* view) const;
|
||||
bool hasResultsOnPage(DocumentView* view, int page) const;
|
||||
int numberOfResultsOnPage(DocumentView* view, int page) const;
|
||||
QList< QRectF > resultsOnPage(DocumentView* view, int page) const;
|
||||
|
||||
enum FindDirection
|
||||
{
|
||||
FindNext,
|
||||
FindPrevious
|
||||
};
|
||||
|
||||
QPersistentModelIndex findResult(DocumentView* view, const QPersistentModelIndex& currentResult, int currentPage, FindDirection direction) const;
|
||||
|
||||
void insertResults(DocumentView* view, int page, const QList< QRectF >& resultsOnPage);
|
||||
void clearResults(DocumentView* view);
|
||||
|
||||
void updateProgress(DocumentView* view);
|
||||
|
||||
protected slots:
|
||||
void on_fetchSurroundingText_finished();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(SearchModel)
|
||||
|
||||
static SearchModel* s_instance;
|
||||
SearchModel(QObject* parent = 0);
|
||||
|
||||
QVector< DocumentView* > m_views;
|
||||
|
||||
QModelIndex findView(DocumentView* view) const;
|
||||
QModelIndex findOrInsertView(DocumentView* view);
|
||||
|
||||
|
||||
typedef QPair< int, QRectF > Result;
|
||||
typedef QList< Result > Results;
|
||||
|
||||
QHash< DocumentView*, Results* > m_results;
|
||||
|
||||
|
||||
typedef QPair< DocumentView*, QByteArray > TextCacheKey;
|
||||
typedef QPair< QString, QString > TextCacheObject;
|
||||
|
||||
struct TextJob
|
||||
{
|
||||
TextCacheKey key;
|
||||
TextCacheObject* object;
|
||||
|
||||
TextJob() : key(), object(0) {}
|
||||
TextJob(const TextCacheKey& key, TextCacheObject* object) : key(key), object(object) {}
|
||||
|
||||
};
|
||||
|
||||
typedef QFutureWatcher< TextJob > TextWatcher;
|
||||
|
||||
mutable QCache< TextCacheKey, TextCacheObject > m_textCache;
|
||||
mutable QHash< TextCacheKey, TextWatcher* > m_textWatchers;
|
||||
|
||||
QString fetchMatchedText(DocumentView* view, const Result& result) const;
|
||||
QString fetchSurroundingText(DocumentView* view, const Result& result) const;
|
||||
|
||||
const TextCacheObject* fetchText(DocumentView* view, const Result& result) const;
|
||||
|
||||
static TextCacheKey textCacheKey(DocumentView* view, const Result& result);
|
||||
static TextJob textJob(const TextCacheKey& key, const Result& result);
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // SEARCHMODEL_H
|
157
sources/searchtask.cpp
Parasts fails
157
sources/searchtask.cpp
Parasts fails
@ -0,0 +1,157 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "searchtask.h"
|
||||
|
||||
#include "model.h"
|
||||
|
||||
#include <QtConcurrentMap>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct Search
|
||||
{
|
||||
Search(const QString& text, const bool matchCase, const bool wholeWords) :
|
||||
text(text),
|
||||
matchCase(matchCase),
|
||||
wholeWords(wholeWords)
|
||||
{
|
||||
}
|
||||
|
||||
const QString& text;
|
||||
const bool matchCase;
|
||||
const bool wholeWords;
|
||||
|
||||
typedef QList< QRectF > result_type;
|
||||
|
||||
result_type operator()(const Model::Page* const page) const
|
||||
{
|
||||
return page->search(text, matchCase, wholeWords);
|
||||
}
|
||||
};
|
||||
|
||||
struct FutureWrapper
|
||||
{
|
||||
FutureWrapper(const QVector< const Model::Page* >& pages, const Search& search) :
|
||||
pages(pages),
|
||||
search(search)
|
||||
{
|
||||
}
|
||||
|
||||
const QVector< const Model::Page* >& pages;
|
||||
const Search& search;
|
||||
|
||||
void cancel()
|
||||
{
|
||||
}
|
||||
|
||||
Search::result_type resultAt(int index)
|
||||
{
|
||||
return search(pages.at(index));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
SearchTask::SearchTask(QObject* parent) : QThread(parent),
|
||||
m_wasCanceled(NotCanceled),
|
||||
m_progress(0),
|
||||
m_pages(),
|
||||
m_text(),
|
||||
m_matchCase(false),
|
||||
m_wholeWords(false),
|
||||
m_beginAtPage(1),
|
||||
m_parallelExecution(false)
|
||||
{
|
||||
}
|
||||
|
||||
void SearchTask::run()
|
||||
{
|
||||
QVector< const Model::Page* > pages;
|
||||
pages.reserve(m_pages.count());
|
||||
|
||||
for(int index = 0, count = m_pages.count(); index < count; ++index)
|
||||
{
|
||||
const int shiftedIndex = (index + m_beginAtPage - 1) % count;
|
||||
pages.append(m_pages.at(shiftedIndex));
|
||||
}
|
||||
|
||||
const Search search(m_text, m_matchCase, m_wholeWords);
|
||||
|
||||
if(m_parallelExecution)
|
||||
{
|
||||
processResults(QtConcurrent::mapped(pages, search));
|
||||
}
|
||||
else
|
||||
{
|
||||
processResults(FutureWrapper(pages, search));
|
||||
}
|
||||
}
|
||||
|
||||
void SearchTask::start(const QVector< Model::Page* >& pages,
|
||||
const QString& text, bool matchCase, bool wholeWords,
|
||||
int beginAtPage, bool parallelExecution)
|
||||
{
|
||||
m_pages = pages;
|
||||
|
||||
m_text = text;
|
||||
m_matchCase = matchCase;
|
||||
m_wholeWords = wholeWords;
|
||||
m_beginAtPage = beginAtPage;
|
||||
m_parallelExecution = parallelExecution;
|
||||
|
||||
resetCancellation();
|
||||
releaseProgress(0);
|
||||
|
||||
QThread::start();
|
||||
}
|
||||
|
||||
template< typename Future >
|
||||
void SearchTask::processResults(Future future)
|
||||
{
|
||||
for(int index = 0, count = m_pages.count(); index < count; ++index)
|
||||
{
|
||||
if(testCancellation())
|
||||
{
|
||||
future.cancel();
|
||||
break;
|
||||
}
|
||||
|
||||
const int shiftedIndex = (index + m_beginAtPage - 1) % count;
|
||||
const QList< QRectF > results = future.resultAt(index);
|
||||
|
||||
emit resultsReady(shiftedIndex, results);
|
||||
|
||||
const int progress = 100 * (index + 1) / m_pages.count();
|
||||
|
||||
releaseProgress(progress);
|
||||
|
||||
emit progressChanged(progress);
|
||||
}
|
||||
|
||||
releaseProgress(0);
|
||||
}
|
||||
|
||||
} // qpdfview
|
178
sources/searchtask.h
Parasts fails
178
sources/searchtask.h
Parasts fails
@ -0,0 +1,178 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEARCHTASK_H
|
||||
#define SEARCHTASK_H
|
||||
|
||||
#include <QRectF>
|
||||
#include <QThread>
|
||||
#include <QVector>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class Page;
|
||||
}
|
||||
|
||||
class SearchTask : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SearchTask(QObject* parent = 0);
|
||||
|
||||
bool wasCanceled() const { return loadCancellation() != NotCanceled; }
|
||||
int progress() const { return acquireProgress(); }
|
||||
|
||||
const QString& text() const { return m_text; }
|
||||
bool matchCase() const { return m_matchCase; }
|
||||
bool wholeWords() const { return m_wholeWords; }
|
||||
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void progressChanged(int progress);
|
||||
|
||||
void resultsReady(int index, const QList< QRectF >& results);
|
||||
|
||||
public slots:
|
||||
void start(const QVector< Model::Page* >& pages,
|
||||
const QString& text, bool matchCase, bool wholeWords,
|
||||
int beginAtPage = 1, bool parallelExecution = false);
|
||||
|
||||
void cancel() { setCancellation(); }
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(SearchTask)
|
||||
|
||||
QAtomicInt m_wasCanceled;
|
||||
mutable QAtomicInt m_progress;
|
||||
|
||||
enum
|
||||
{
|
||||
NotCanceled = 0,
|
||||
Canceled = 1
|
||||
};
|
||||
|
||||
void setCancellation();
|
||||
void resetCancellation();
|
||||
bool testCancellation();
|
||||
int loadCancellation() const;
|
||||
|
||||
void releaseProgress(int value);
|
||||
int acquireProgress() const;
|
||||
int loadProgress() const;
|
||||
|
||||
template< typename Future >
|
||||
void processResults(Future future);
|
||||
|
||||
|
||||
QVector< Model::Page* > m_pages;
|
||||
|
||||
QString m_text;
|
||||
bool m_matchCase;
|
||||
bool m_wholeWords;
|
||||
int m_beginAtPage;
|
||||
bool m_parallelExecution;
|
||||
|
||||
};
|
||||
|
||||
#if QT_VERSION > QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
inline void SearchTask::setCancellation()
|
||||
{
|
||||
m_wasCanceled.storeRelease(Canceled);
|
||||
}
|
||||
|
||||
inline void SearchTask::resetCancellation()
|
||||
{
|
||||
m_wasCanceled.storeRelease(NotCanceled);
|
||||
}
|
||||
|
||||
inline bool SearchTask::testCancellation()
|
||||
{
|
||||
return m_wasCanceled.load() != NotCanceled;
|
||||
}
|
||||
|
||||
inline int SearchTask::loadCancellation() const
|
||||
{
|
||||
return m_wasCanceled.load();
|
||||
}
|
||||
|
||||
inline void SearchTask::releaseProgress(int value)
|
||||
{
|
||||
m_progress.storeRelease(value);
|
||||
}
|
||||
|
||||
inline int SearchTask::acquireProgress() const
|
||||
{
|
||||
return m_progress.loadAcquire();
|
||||
}
|
||||
|
||||
inline int SearchTask::loadProgress() const
|
||||
{
|
||||
return m_progress.load();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void SearchTask::setCancellation()
|
||||
{
|
||||
m_wasCanceled.fetchAndStoreRelease(Canceled);
|
||||
}
|
||||
|
||||
inline void SearchTask::resetCancellation()
|
||||
{
|
||||
m_wasCanceled.fetchAndStoreRelease(NotCanceled);
|
||||
}
|
||||
|
||||
inline bool SearchTask::testCancellation()
|
||||
{
|
||||
return !m_wasCanceled.testAndSetRelaxed(NotCanceled, NotCanceled);
|
||||
}
|
||||
|
||||
inline int SearchTask::loadCancellation() const
|
||||
{
|
||||
return m_wasCanceled;
|
||||
}
|
||||
|
||||
inline void SearchTask::releaseProgress(int value)
|
||||
{
|
||||
m_progress.fetchAndStoreRelease(value);
|
||||
}
|
||||
|
||||
inline int SearchTask::acquireProgress() const
|
||||
{
|
||||
return m_progress.fetchAndAddAcquire(0);
|
||||
}
|
||||
|
||||
inline int SearchTask::loadProgress() const
|
||||
{
|
||||
return m_progress;
|
||||
}
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // SEARCHTHREAD_H
|
1231
sources/settings.cpp
Parasts fails
1231
sources/settings.cpp
Parasts fails
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
706
sources/settings.h
Parasts fails
706
sources/settings.h
Parasts fails
@ -0,0 +1,706 @@
|
||||
/*
|
||||
|
||||
Copyright 2015 S. Razi Alavizadeh
|
||||
Copyright 2012-2015, 2018 Adam Reichold
|
||||
Copyright 2012 Alexander Volkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <QColor>
|
||||
#include <QIcon>
|
||||
#include <QKeySequence>
|
||||
#include <QObject>
|
||||
#include <QPrinter>
|
||||
|
||||
class QSettings;
|
||||
|
||||
#include "global.h"
|
||||
#include "printoptions.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class Settings : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static Settings* instance();
|
||||
~Settings();
|
||||
|
||||
// page item
|
||||
|
||||
class PageItem
|
||||
{
|
||||
public:
|
||||
void sync();
|
||||
|
||||
int cacheSize() const { return m_cacheSize; }
|
||||
void setCacheSize(int cacheSize);
|
||||
|
||||
bool useTiling() const { return m_useTiling; }
|
||||
void setUseTiling(bool useTiling);
|
||||
|
||||
int tileSize() const { return m_tileSize; }
|
||||
|
||||
const QIcon& progressIcon() const { return m_progressIcon; }
|
||||
void setProgressIcon(const QIcon& progressIcon) { m_progressIcon = progressIcon; }
|
||||
|
||||
const QIcon& errorIcon() const { return m_errorIcon; }
|
||||
void setErrorIcon(const QIcon& errorIcon) { m_errorIcon = errorIcon; }
|
||||
|
||||
bool keepObsoletePixmaps() const { return m_keepObsoletePixmaps; }
|
||||
void setKeepObsoletePixmaps(bool keepObsoletePixmaps);
|
||||
|
||||
bool useDevicePixelRatio() const { return m_useDevicePixelRatio; }
|
||||
void setUseDevicePixelRatio(bool useDevicePixelRatio);
|
||||
|
||||
bool decoratePages() const { return m_decoratePages; }
|
||||
void setDecoratePages(bool decoratePages);
|
||||
|
||||
bool decorateLinks() const { return m_decorateLinks; }
|
||||
void setDecorateLinks(bool decorateLinks);
|
||||
|
||||
bool decorateFormFields() const { return m_decorateFormFields; }
|
||||
void setDecorateFormFields(bool decorateFormFields);
|
||||
|
||||
const QColor& backgroundColor() const { return m_backgroundColor; }
|
||||
void setBackgroundColor(const QColor& backgroundColor);
|
||||
|
||||
const QColor& paperColor() const { return m_paperColor; }
|
||||
void setPaperColor(const QColor& paperColor);
|
||||
|
||||
const QColor& highlightColor() const { return m_highlightColor; }
|
||||
void setHighlightColor(const QColor& highlightColor);
|
||||
|
||||
QColor annotationColor() const;
|
||||
void setAnnotationColor(const QColor& annotationColor);
|
||||
|
||||
Qt::KeyboardModifiers copyToClipboardModifiers() const;
|
||||
void setCopyToClipboardModifiers(Qt::KeyboardModifiers modifiers);
|
||||
|
||||
Qt::KeyboardModifiers addAnnotationModifiers() const;
|
||||
void setAddAnnotationModifiers(Qt::KeyboardModifiers modifiers);
|
||||
|
||||
Qt::KeyboardModifiers zoomToSelectionModifiers() const;
|
||||
void setZoomToSelectionModifiers(Qt::KeyboardModifiers modifiers);
|
||||
|
||||
Qt::KeyboardModifiers openInSourceEditorModifiers() const;
|
||||
void setOpenInSourceEditorModifiers(Qt::KeyboardModifiers modifiers);
|
||||
|
||||
bool annotationOverlay() const;
|
||||
void setAnnotationOverlay(bool overlay);
|
||||
|
||||
bool formFieldOverlay() const;
|
||||
void setFormFieldOverlay(bool overlay);
|
||||
|
||||
private:
|
||||
PageItem(QSettings* settings);
|
||||
friend class Settings;
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
int m_cacheSize;
|
||||
|
||||
bool m_useTiling;
|
||||
int m_tileSize;
|
||||
|
||||
QIcon m_progressIcon;
|
||||
QIcon m_errorIcon;
|
||||
|
||||
bool m_keepObsoletePixmaps;
|
||||
bool m_useDevicePixelRatio;
|
||||
|
||||
bool m_decoratePages;
|
||||
bool m_decorateLinks;
|
||||
bool m_decorateFormFields;
|
||||
|
||||
QColor m_backgroundColor;
|
||||
QColor m_paperColor;
|
||||
|
||||
QColor m_highlightColor;
|
||||
|
||||
};
|
||||
|
||||
// presentation view
|
||||
|
||||
class PresentationView
|
||||
{
|
||||
public:
|
||||
bool synchronize() const;
|
||||
void setSynchronize(bool synchronize);
|
||||
|
||||
int screen() const;
|
||||
void setScreen(int screen);
|
||||
|
||||
QColor backgroundColor() const;
|
||||
void setBackgroundColor(const QColor& backgroundColor);
|
||||
|
||||
private:
|
||||
PresentationView(QSettings* settings);
|
||||
friend class Settings;
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
};
|
||||
|
||||
// document view
|
||||
|
||||
class DocumentView
|
||||
{
|
||||
public:
|
||||
void sync();
|
||||
|
||||
bool openUrl() const;
|
||||
void setOpenUrl(bool openUrl);
|
||||
|
||||
bool autoRefresh() const;
|
||||
void setAutoRefresh(bool autoRefresh);
|
||||
|
||||
int autoRefreshTimeout() const;
|
||||
|
||||
bool prefetch() const { return m_prefetch; }
|
||||
void setPrefetch(bool prefetch);
|
||||
|
||||
int prefetchDistance() const { return m_prefetchDistance; }
|
||||
void setPrefetchDistance(int prefetchDistance);
|
||||
|
||||
int prefetchTimeout() const;
|
||||
|
||||
int pagesPerRow() const { return m_pagesPerRow; }
|
||||
void setPagesPerRow(int pagesPerRow);
|
||||
|
||||
bool minimalScrolling() const { return m_minimalScrolling; }
|
||||
void setMinimalScrolling(bool minimalScrolling);
|
||||
|
||||
bool highlightCurrentThumbnail() const { return m_highlightCurrentThumbnail; }
|
||||
void setHighlightCurrentThumbnail(bool highlightCurrentThumbnail);
|
||||
|
||||
bool limitThumbnailsToResults() const { return m_limitThumbnailsToResults; }
|
||||
void setLimitThumbnailsToResults(bool limitThumbnailsToResults);
|
||||
|
||||
qreal minimumScaleFactor() const;
|
||||
qreal maximumScaleFactor() const;
|
||||
|
||||
qreal zoomFactor() const;
|
||||
void setZoomFactor(qreal zoomFactor);
|
||||
|
||||
qreal pageSpacing() const { return m_pageSpacing; }
|
||||
void setPageSpacing(qreal pageSpacing);
|
||||
|
||||
qreal thumbnailSpacing() const { return m_thumbnailSpacing; }
|
||||
void setThumbnailSpacing(qreal thumbnailSpacing);
|
||||
|
||||
qreal thumbnailSize() const { return m_thumbnailSize; }
|
||||
void setThumbnailSize(qreal thumbnailSize);
|
||||
|
||||
bool matchCase() const;
|
||||
void setMatchCase(bool matchCase);
|
||||
|
||||
bool wholeWords() const;
|
||||
void setWholeWords(bool wholeWords);
|
||||
|
||||
bool parallelSearchExecution() const;
|
||||
void setParallelSearchExecution(bool parallelSearchExecution);
|
||||
|
||||
int highlightDuration() const;
|
||||
void setHighlightDuration(int highlightDuration);
|
||||
|
||||
QString sourceEditor() const;
|
||||
void setSourceEditor(const QString& sourceEditor);
|
||||
|
||||
Qt::KeyboardModifiers zoomModifiers() const;
|
||||
void setZoomModifiers(Qt::KeyboardModifiers zoomModifiers);
|
||||
|
||||
Qt::KeyboardModifiers rotateModifiers() const;
|
||||
void setRotateModifiers(Qt::KeyboardModifiers rotateModifiers);
|
||||
|
||||
Qt::KeyboardModifiers scrollModifiers() const;
|
||||
void setScrollModifiers(Qt::KeyboardModifiers scrollModifiers);
|
||||
|
||||
// per-tab settings
|
||||
|
||||
bool continuousMode() const;
|
||||
void setContinuousMode(bool continuousMode);
|
||||
|
||||
LayoutMode layoutMode() const;
|
||||
void setLayoutMode(LayoutMode layoutMode);
|
||||
|
||||
bool rightToLeftMode() const;
|
||||
void setRightToLeftMode(bool rightToLeftMode);
|
||||
|
||||
ScaleMode scaleMode() const;
|
||||
void setScaleMode(ScaleMode scaleMode);
|
||||
|
||||
qreal scaleFactor() const;
|
||||
void setScaleFactor(qreal scaleFactor);
|
||||
|
||||
Rotation rotation() const;
|
||||
void setRotation(Rotation rotation);
|
||||
|
||||
bool invertColors() const;
|
||||
void setInvertColors(bool invertColors);
|
||||
|
||||
bool convertToGrayscale() const;
|
||||
void setConvertToGrayscale(bool convertToGrayscale);
|
||||
|
||||
bool trimMargins() const;
|
||||
void setTrimMargins(bool trimMargins);
|
||||
|
||||
CompositionMode compositionMode() const;
|
||||
void setCompositionMode(CompositionMode compositionMode);
|
||||
|
||||
bool highlightAll() const;
|
||||
void setHighlightAll(bool highlightAll);
|
||||
|
||||
private:
|
||||
DocumentView(QSettings* settings);
|
||||
friend class Settings;
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
bool m_prefetch;
|
||||
int m_prefetchDistance;
|
||||
|
||||
int m_pagesPerRow;
|
||||
|
||||
bool m_minimalScrolling;
|
||||
|
||||
bool m_highlightCurrentThumbnail;
|
||||
bool m_limitThumbnailsToResults;
|
||||
|
||||
qreal m_pageSpacing;
|
||||
qreal m_thumbnailSpacing;
|
||||
|
||||
qreal m_thumbnailSize;
|
||||
|
||||
};
|
||||
|
||||
// main window
|
||||
|
||||
class MainWindow
|
||||
{
|
||||
public:
|
||||
bool trackRecentlyUsed() const;
|
||||
void setTrackRecentlyUsed(bool trackRecentlyUsed);
|
||||
|
||||
int recentlyUsedCount() const;
|
||||
void setRecentlyUsedCount(int recentlyUsedCount);
|
||||
|
||||
QStringList recentlyUsed() const;
|
||||
void setRecentlyUsed(const QStringList& recentlyUsed);
|
||||
|
||||
bool keepRecentlyClosed() const;
|
||||
void setKeepRecentlyClosed(bool keepRecentlyClosed);
|
||||
|
||||
int recentlyClosedCount() const;
|
||||
void setRecentlyClosedCount(int recentlyClosedCount);
|
||||
|
||||
bool restoreTabs() const;
|
||||
void setRestoreTabs(bool restoreTabs);
|
||||
|
||||
bool restoreBookmarks() const;
|
||||
void setRestoreBookmarks(bool restoreBookmarks);
|
||||
|
||||
bool restorePerFileSettings() const;
|
||||
void setRestorePerFileSettings(bool restorePerFileSettings);
|
||||
|
||||
int perFileSettingsLimit() const;
|
||||
|
||||
int saveDatabaseInterval() const;
|
||||
void setSaveDatabaseInterval(int saveDatabaseInterval);
|
||||
|
||||
int currentTabIndex() const;
|
||||
void setCurrentTabIndex(int currentTabIndex);
|
||||
|
||||
int tabPosition() const;
|
||||
void setTabPosition(int tabPosition);
|
||||
|
||||
int tabVisibility() const;
|
||||
void setTabVisibility(int tabVisibility);
|
||||
|
||||
bool spreadTabs() const;
|
||||
void setSpreadTabs(bool spreadTabs);
|
||||
|
||||
bool newTabNextToCurrentTab() const;
|
||||
void setNewTabNextToCurrentTab(bool newTabNextToCurrentTab);
|
||||
|
||||
bool exitAfterLastTab() const;
|
||||
void setExitAfterLastTab(bool exitAfterLastTab);
|
||||
|
||||
bool documentTitleAsTabTitle() const;
|
||||
void setDocumentTitleAsTabTitle(bool documentTitleAsTabTitle);
|
||||
|
||||
bool currentPageInWindowTitle() const;
|
||||
void setCurrentPageInWindowTitle(bool currentPageInWindowTitle);
|
||||
|
||||
bool instanceNameInWindowTitle() const;
|
||||
void setInstanceNameInWindowTitle(bool instanceNameInWindowTitle);
|
||||
|
||||
bool extendedSearchDock() const;
|
||||
void setExtendedSearchDock(bool extendedSearchDock);
|
||||
|
||||
bool usePageLabel() const;
|
||||
void setUsePageLabel(bool usePageLabel);
|
||||
|
||||
bool synchronizeOutlineView() const;
|
||||
void setSynchronizeOutlineView(bool synchronizeOutlineView);
|
||||
|
||||
bool synchronizeSplitViews() const;
|
||||
void setSynchronizeSplitViews(bool synchronizeSplitViews);
|
||||
|
||||
QStringList fileToolBar() const;
|
||||
void setFileToolBar(const QStringList& fileToolBar);
|
||||
|
||||
QStringList editToolBar() const;
|
||||
void setEditToolBar(const QStringList& editToolBar);
|
||||
|
||||
QStringList viewToolBar() const;
|
||||
void setViewToolBar(const QStringList& viewToolBar);
|
||||
|
||||
QStringList documentContextMenu() const;
|
||||
void setDocumentContextMenu(const QStringList& documentContextMenu);
|
||||
|
||||
QStringList tabContextMenu() const;
|
||||
void setTabContextMenu(const QStringList& tabContextMenu);
|
||||
|
||||
bool scrollableMenus() const;
|
||||
void setScrollableMenus(bool scrollableMenus);
|
||||
|
||||
bool searchableMenus() const;
|
||||
void setSearchableMenus(bool searchableMenus);
|
||||
|
||||
bool toggleToolAndMenuBarsWithFullscreen() const;
|
||||
void setToggleToolAndMenuBarsWithFullscreen(bool toggleToolAndMenuBarsWithFullscreen) const;
|
||||
|
||||
bool hasIconTheme() const;
|
||||
QString iconTheme() const;
|
||||
|
||||
bool hasStyleSheet() const;
|
||||
QString styleSheet() const;
|
||||
|
||||
QByteArray geometry() const;
|
||||
void setGeometry(const QByteArray& geometry);
|
||||
|
||||
QByteArray state() const;
|
||||
void setState(const QByteArray& state);
|
||||
|
||||
QString openPath() const;
|
||||
void setOpenPath(const QString& openPath);
|
||||
|
||||
QString savePath() const;
|
||||
void setSavePath(const QString& savePath);
|
||||
|
||||
QSize settingsDialogSize(QSize sizeHint) const;
|
||||
void setSettingsDialogSize(QSize settingsDialogSize);
|
||||
|
||||
QSize fontsDialogSize(QSize sizeHint) const;
|
||||
void setFontsDialogSize(QSize fontsDialogSize);
|
||||
|
||||
QSize contentsDialogSize(QSize sizeHint) const;
|
||||
void setContentsDialogSize(QSize contentsDialogSize);
|
||||
|
||||
private:
|
||||
MainWindow(QSettings* settings);
|
||||
friend class Settings;
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
};
|
||||
|
||||
// print dialog
|
||||
|
||||
class PrintDialog
|
||||
{
|
||||
public:
|
||||
bool collateCopies() const;
|
||||
void setCollateCopies(bool collateCopies);
|
||||
|
||||
QPrinter::PageOrder pageOrder() const;
|
||||
void setPageOrder(QPrinter::PageOrder pageOrder);
|
||||
|
||||
QPrinter::Orientation orientation() const;
|
||||
void setOrientation(QPrinter::Orientation orientation);
|
||||
|
||||
QPrinter::ColorMode colorMode() const;
|
||||
void setColorMode(QPrinter::ColorMode colorMode);
|
||||
|
||||
QPrinter::DuplexMode duplex() const;
|
||||
void setDuplex(QPrinter::DuplexMode duplex);
|
||||
|
||||
bool fitToPage() const;
|
||||
void setFitToPage(bool fitToPage);
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
|
||||
|
||||
PrintOptions::PageSet pageSet() const;
|
||||
void setPageSet(PrintOptions::PageSet pageSet);
|
||||
|
||||
PrintOptions::NumberUp numberUp() const;
|
||||
void setNumberUp(PrintOptions::NumberUp numberUp);
|
||||
|
||||
PrintOptions::NumberUpLayout numberUpLayout() const;
|
||||
void setNumberUpLayout(PrintOptions::NumberUpLayout numberUpLayout);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
private:
|
||||
PrintDialog(QSettings* settings);
|
||||
friend class Settings;
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
};
|
||||
|
||||
void sync();
|
||||
|
||||
PageItem& pageItem() { return m_pageItem; }
|
||||
PresentationView& presentationView() { return m_presentationView; }
|
||||
DocumentView& documentView() { return m_documentView; }
|
||||
MainWindow& mainWindow() { return m_mainWindow; }
|
||||
PrintDialog& printDialog() { return m_printDialog; }
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(Settings)
|
||||
|
||||
static Settings* s_instance;
|
||||
Settings(QObject* parent = 0);
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
PageItem m_pageItem;
|
||||
PresentationView m_presentationView;
|
||||
DocumentView m_documentView;
|
||||
MainWindow m_mainWindow;
|
||||
PrintDialog m_printDialog;
|
||||
|
||||
};
|
||||
|
||||
// defaults
|
||||
|
||||
class Defaults
|
||||
{
|
||||
public:
|
||||
class PageItem
|
||||
{
|
||||
public:
|
||||
static int cacheSize() { return 32 * 1024; }
|
||||
|
||||
static bool useTiling() { return false; }
|
||||
static int tileSize() { return 1024; }
|
||||
|
||||
static bool keepObsoletePixmaps() { return false; }
|
||||
static bool useDevicePixelRatio() { return false; }
|
||||
|
||||
static bool decoratePages() { return true; }
|
||||
static bool decorateLinks() { return true; }
|
||||
static bool decorateFormFields() { return true; }
|
||||
|
||||
static QColor backgroundColor() { return Qt::darkGray; }
|
||||
static QColor paperColor() { return Qt::white; }
|
||||
|
||||
static QColor highlightColor() { return Qt::yellow; }
|
||||
static QColor annotationColor() { return Qt::yellow; }
|
||||
|
||||
static Qt::KeyboardModifiers copyToClipboardModifiers() { return Qt::ShiftModifier; }
|
||||
static Qt::KeyboardModifiers addAnnotationModifiers() { return Qt::ControlModifier; }
|
||||
static Qt::KeyboardModifiers zoomToSelectionModifiers() { return Qt::ShiftModifier | Qt::ControlModifier; }
|
||||
static Qt::KeyboardModifiers openInSourceEditorModifiers() { return Qt::NoModifier; }
|
||||
|
||||
static bool annotationOverlay() { return false; }
|
||||
static bool formFieldOverlay() { return true; }
|
||||
|
||||
private:
|
||||
PageItem() {}
|
||||
|
||||
};
|
||||
|
||||
class PresentationView
|
||||
{
|
||||
public:
|
||||
static bool synchronize() { return false; }
|
||||
static int screen() { return -1; }
|
||||
|
||||
static QColor backgroundColor() { return QColor(); }
|
||||
|
||||
private:
|
||||
PresentationView() {}
|
||||
|
||||
};
|
||||
|
||||
class DocumentView
|
||||
{
|
||||
public:
|
||||
static bool openUrl() { return false; }
|
||||
|
||||
static bool autoRefresh() { return false; }
|
||||
|
||||
static int autoRefreshTimeout() { return 750; }
|
||||
|
||||
static bool prefetch() { return false; }
|
||||
static int prefetchDistance() { return 1; }
|
||||
|
||||
static int prefetchTimeout() { return 250; }
|
||||
|
||||
static int pagesPerRow() { return 3; }
|
||||
|
||||
static bool minimalScrolling() { return false; }
|
||||
|
||||
static bool highlightCurrentThumbnail() { return false; }
|
||||
static bool limitThumbnailsToResults() { return false; }
|
||||
|
||||
static qreal minimumScaleFactor() { return 0.1; }
|
||||
static qreal maximumScaleFactor() { return 50.0; }
|
||||
|
||||
static qreal zoomFactor() { return 1.1; }
|
||||
|
||||
static qreal pageSpacing() { return 5.0; }
|
||||
static qreal thumbnailSpacing() { return 3.0; }
|
||||
|
||||
static qreal thumbnailSize() { return 150.0; }
|
||||
|
||||
static CompositionMode compositionMode() { return DefaultCompositionMode; }
|
||||
|
||||
static bool matchCase() { return false; }
|
||||
static bool wholeWords() { return false; }
|
||||
static bool parallelSearchExecution() { return false; }
|
||||
|
||||
static int highlightDuration() { return 5 * 1000; }
|
||||
static QString sourceEditor() { return QString(); }
|
||||
|
||||
static Qt::KeyboardModifiers zoomModifiers() { return Qt::ControlModifier; }
|
||||
static Qt::KeyboardModifiers rotateModifiers() { return Qt::ShiftModifier; }
|
||||
static Qt::KeyboardModifiers scrollModifiers() { return Qt::AltModifier; }
|
||||
|
||||
// per-tab defaults
|
||||
|
||||
static bool continuousMode() { return false; }
|
||||
static LayoutMode layoutMode() { return SinglePageMode; }
|
||||
static bool rightToLeftMode();
|
||||
|
||||
static ScaleMode scaleMode() { return ScaleFactorMode; }
|
||||
static qreal scaleFactor() { return 1.0; }
|
||||
static Rotation rotation() { return RotateBy0; }
|
||||
|
||||
static bool invertColors() { return false; }
|
||||
static bool convertToGrayscale() { return false; }
|
||||
static bool trimMargins() { return false; }
|
||||
|
||||
static bool highlightAll() { return false; }
|
||||
|
||||
private:
|
||||
DocumentView() {}
|
||||
|
||||
};
|
||||
|
||||
class MainWindow
|
||||
{
|
||||
public:
|
||||
static bool trackRecentlyUsed() { return false; }
|
||||
static int recentlyUsedCount() { return 10; }
|
||||
|
||||
static bool keepRecentlyClosed() { return false; }
|
||||
static int recentlyClosedCount() { return 5; }
|
||||
|
||||
static bool restoreTabs() { return false; }
|
||||
static bool restoreBookmarks() { return false; }
|
||||
static bool restorePerFileSettings() { return false; }
|
||||
|
||||
static int perFileSettingsLimit() { return 1000; }
|
||||
|
||||
static int saveDatabaseInterval() { return 5 * 60 * 1000; }
|
||||
|
||||
static int tabPosition() { return 0; }
|
||||
static int tabVisibility() { return 0; }
|
||||
|
||||
static bool spreadTabs() { return false; }
|
||||
|
||||
static bool newTabNextToCurrentTab() { return true; }
|
||||
static bool exitAfterLastTab() { return false; }
|
||||
|
||||
static bool documentTitleAsTabTitle() { return true; }
|
||||
|
||||
static bool currentPageInWindowTitle() { return false; }
|
||||
static bool instanceNameInWindowTitle() { return false; }
|
||||
|
||||
static bool extendedSearchDock() { return false; }
|
||||
|
||||
static bool usePageLabel() { return true; }
|
||||
|
||||
static bool synchronizeOutlineView() { return false; }
|
||||
static bool synchronizeSplitViews() { return true; }
|
||||
|
||||
static QStringList fileToolBar() { return QStringList() << "openInNewTab" << "refresh"; }
|
||||
static QStringList editToolBar() { return QStringList() << "currentPage" << "previousPage" << "nextPage"; }
|
||||
static QStringList viewToolBar() { return QStringList() << "scaleFactor" << "zoomIn" << "zoomOut"; }
|
||||
|
||||
static QStringList documentContextMenu() { return QStringList() << "previousPage" << "nextPage" << "firstPage" << "lastPage" << "separator" << "jumpToPage" << "jumpBackward" << "jumpForward" << "separator" << "setFirstPage" << "separator" << "findPrevious" << "findNext" << "cancelSearch"; }
|
||||
static QStringList tabContexntMenu() { return QStringList() << "openCopyInNewTab" << "openCopyInNewWindow" << "openContainingFolder" << "separator" << "splitViewHorizontally" << "splitViewVertically" << "closeCurrentView" << "separator" << "closeAllTabs" << "closeAllTabsButThisOne" << "closeAllTabsToTheLeft" << "closeAllTabsToTheRight"; }
|
||||
|
||||
static bool scrollableMenus() { return false; }
|
||||
static bool searchableMenus() { return false; }
|
||||
|
||||
static bool toggleToolAndMenuBarsWithFullscreen() { return false; }
|
||||
|
||||
static QString path();
|
||||
|
||||
private:
|
||||
MainWindow() {}
|
||||
|
||||
};
|
||||
|
||||
class PrintDialog
|
||||
{
|
||||
public:
|
||||
static bool collateCopies() { return false; }
|
||||
|
||||
static QPrinter::PageOrder pageOrder() { return QPrinter::FirstPageFirst; }
|
||||
|
||||
static QPrinter::Orientation orientation() { return QPrinter::Portrait; }
|
||||
|
||||
static QPrinter::ColorMode colorMode() { return QPrinter::Color; }
|
||||
|
||||
static QPrinter::DuplexMode duplex() { return QPrinter::DuplexNone; }
|
||||
|
||||
static bool fitToPage() { return false; }
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
|
||||
|
||||
static PrintOptions::PageSet pageSet() { return PrintOptions::AllPages; }
|
||||
|
||||
static PrintOptions::NumberUp numberUp() { return PrintOptions::SinglePage; }
|
||||
static PrintOptions::NumberUpLayout numberUpLayout() { return PrintOptions::LeftRightTopBottom; }
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
private:
|
||||
PrintDialog() {}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
Defaults() {}
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // SETTINGS_H
|
878
sources/settingsdialog.cpp
Parasts fails
878
sources/settingsdialog.cpp
Parasts fails
@ -0,0 +1,878 @@
|
||||
/*
|
||||
|
||||
Copyright 2015 S. Razi Alavizadeh
|
||||
Copyright 2012-2015 Adam Reichold
|
||||
Copyright 2012 Alexander Volkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "settingsdialog.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCheckBox>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFormLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QHeaderView>
|
||||
#include <QPushButton>
|
||||
#include <QShortcut>
|
||||
#include <QTableView>
|
||||
|
||||
#include "settings.h"
|
||||
#include "model.h"
|
||||
#include "pluginhandler.h"
|
||||
#include "shortcuthandler.h"
|
||||
#include "documentview.h"
|
||||
#include "miscellaneous.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace qpdfview;
|
||||
|
||||
void addSettingsWidget(QTabWidget* tabWidget, SettingsWidget*& settingsWidget, PluginHandler::FileType fileType)
|
||||
{
|
||||
settingsWidget = PluginHandler::instance()->createSettingsWidget(fileType, tabWidget);
|
||||
|
||||
if(settingsWidget != 0)
|
||||
{
|
||||
tabWidget->addTab(settingsWidget, PluginHandler::fileTypeName(fileType));
|
||||
}
|
||||
}
|
||||
|
||||
void setCurrentIndexFromData(QComboBox* comboBox, int data)
|
||||
{
|
||||
comboBox->setCurrentIndex(comboBox->findData(data));
|
||||
}
|
||||
|
||||
int dataFromCurrentIndex(const QComboBox* comboBox)
|
||||
{
|
||||
return comboBox->itemData(comboBox->currentIndex()).toInt();
|
||||
}
|
||||
|
||||
void setCurrentTextToColorName(QComboBox* comboBox, const QColor& color)
|
||||
{
|
||||
comboBox->lineEdit()->setText(color.isValid() ? color.name() : QString());
|
||||
}
|
||||
|
||||
QColor validColorFromCurrentText(const QComboBox* comboBox, const QColor& defaultColor)
|
||||
{
|
||||
const QColor color(comboBox->currentText());
|
||||
|
||||
return color.isValid() ? color : defaultColor;
|
||||
}
|
||||
|
||||
void setCurrentIndexFromKeyboardModifiers(QComboBox* comboBox, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
comboBox->setCurrentIndex(comboBox->findData(static_cast< int >(modifiers)));
|
||||
}
|
||||
|
||||
Qt::KeyboardModifier keyboardModifierFromCurrentIndex(const QComboBox* comboBox)
|
||||
{
|
||||
return static_cast< Qt::KeyboardModifier >(comboBox->itemData(comboBox->currentIndex()).toInt());
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
Settings* SettingsDialog::s_settings = 0;
|
||||
|
||||
SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent)
|
||||
{
|
||||
if(s_settings == 0)
|
||||
{
|
||||
s_settings = Settings::instance();
|
||||
}
|
||||
|
||||
setWindowTitle(tr("Settings") + QLatin1String(" - qpdfview"));
|
||||
|
||||
m_graphicsTabWidget = new QTabWidget(this);
|
||||
m_graphicsTabWidget->addTab(new QWidget(this), tr("General"));
|
||||
|
||||
addSettingsWidget(m_graphicsTabWidget, m_pdfSettingsWidget, PluginHandler::PDF);
|
||||
addSettingsWidget(m_graphicsTabWidget, m_psSettingsWidget, PluginHandler::PS);
|
||||
addSettingsWidget(m_graphicsTabWidget, m_djvuSettingsWidget, PluginHandler::DjVu);
|
||||
|
||||
m_graphicsLayout = new QFormLayout(m_graphicsTabWidget->widget(0));
|
||||
|
||||
m_shortcutsTableView = new QTableView(this);
|
||||
|
||||
m_shortcutsTableView->setModel(ShortcutHandler::instance());
|
||||
|
||||
connect(this, SIGNAL(accepted()), ShortcutHandler::instance(), SLOT(submit()));
|
||||
connect(this, SIGNAL(rejected()), ShortcutHandler::instance(), SLOT(revert()));
|
||||
|
||||
m_shortcutsTableView->setFrameShape(QFrame::NoFrame);
|
||||
m_shortcutsTableView->setAlternatingRowColors(true);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
|
||||
m_shortcutsTableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||
m_shortcutsTableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
|
||||
#else
|
||||
|
||||
m_shortcutsTableView->horizontalHeader()->setResizeMode(0, QHeaderView::ResizeToContents);
|
||||
m_shortcutsTableView->horizontalHeader()->setResizeMode(1, QHeaderView::Stretch);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
m_shortcutsTableView->verticalHeader()->setVisible(false);
|
||||
|
||||
m_tabWidget = new QTabWidget(this);
|
||||
m_tabWidget->addTab(new QWidget(this), tr("&Behavior"));
|
||||
m_tabWidget->addTab(m_graphicsTabWidget, tr("&Graphics"));
|
||||
m_tabWidget->addTab(new QWidget(this), tr("&Interface"));
|
||||
m_tabWidget->addTab(m_shortcutsTableView, tr("&Shortcuts"));
|
||||
m_tabWidget->addTab(new QWidget(this), tr("&Modifiers"));
|
||||
|
||||
m_dialogButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
|
||||
connect(m_dialogButtonBox, SIGNAL(accepted()), SLOT(accept()));
|
||||
connect(m_dialogButtonBox, SIGNAL(rejected()), SLOT(reject()));
|
||||
|
||||
m_defaultsButton = m_dialogButtonBox->addButton(tr("Defaults"), QDialogButtonBox::ResetRole);
|
||||
connect(m_defaultsButton, SIGNAL(clicked()), SLOT(reset()));
|
||||
|
||||
m_defaultsOnCurrentTabButton = m_dialogButtonBox->addButton(tr("Defaults on current tab"), QDialogButtonBox::ResetRole);
|
||||
connect(m_defaultsOnCurrentTabButton, SIGNAL(clicked()), SLOT(resetCurrentTab()));
|
||||
|
||||
m_behaviorLayout = new QFormLayout(m_tabWidget->widget(0));
|
||||
m_interfaceLayout = new QFormLayout(m_tabWidget->widget(2));
|
||||
|
||||
m_wheelModifiersGroupBox = new QGroupBox(tr("Mouse wheel modifiers"));
|
||||
m_wheelModifiersLayout = new QFormLayout(m_wheelModifiersGroupBox);
|
||||
|
||||
m_buttonModifiersGroupBox = new QGroupBox(tr("Mouse button modifiers"));
|
||||
m_buttonModifiersLayout = new QFormLayout(m_buttonModifiersGroupBox);
|
||||
|
||||
QWidget* modifiersTab = m_tabWidget->widget(4);
|
||||
QVBoxLayout* modifiersLayout = new QVBoxLayout(modifiersTab);
|
||||
modifiersTab->setLayout(modifiersLayout);
|
||||
modifiersLayout->addWidget(m_wheelModifiersGroupBox);
|
||||
modifiersLayout->addWidget(m_buttonModifiersGroupBox);
|
||||
modifiersLayout->addStretch();
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
setLayout(layout);
|
||||
layout->addWidget(m_tabWidget);
|
||||
layout->addWidget(m_dialogButtonBox);
|
||||
|
||||
resize(s_settings->mainWindow().settingsDialogSize(sizeHint()));
|
||||
|
||||
createBehaviorTab();
|
||||
createGraphicsTab();
|
||||
createInterfaceTab();
|
||||
createModifiersTab();
|
||||
}
|
||||
|
||||
SettingsDialog::~SettingsDialog()
|
||||
{
|
||||
s_settings->mainWindow().setSettingsDialogSize(size());
|
||||
}
|
||||
|
||||
void SettingsDialog::accept()
|
||||
{
|
||||
QDialog::accept();
|
||||
|
||||
acceptBehaivorTab();
|
||||
|
||||
acceptGraphicsTab();
|
||||
|
||||
acceptInterfaceTab();
|
||||
|
||||
acceptModifiersTab();
|
||||
}
|
||||
|
||||
void SettingsDialog::reset()
|
||||
{
|
||||
resetBehaviorTab();
|
||||
|
||||
resetGraphicsTab();
|
||||
|
||||
resetInterfaceTab();
|
||||
|
||||
ShortcutHandler::instance()->reset();
|
||||
|
||||
resetModifiersTab();
|
||||
}
|
||||
|
||||
void SettingsDialog::resetCurrentTab()
|
||||
{
|
||||
switch(m_tabWidget->currentIndex())
|
||||
{
|
||||
default:
|
||||
reset();
|
||||
break;
|
||||
case 0:
|
||||
resetBehaviorTab();
|
||||
break;
|
||||
case 1:
|
||||
resetGraphicsTab();
|
||||
break;
|
||||
case 2:
|
||||
resetInterfaceTab();
|
||||
break;
|
||||
case 3:
|
||||
ShortcutHandler::instance()->reset();
|
||||
break;
|
||||
case 4:
|
||||
resetModifiersTab();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::createBehaviorTab()
|
||||
{
|
||||
m_openUrlCheckBox = addCheckBox(m_behaviorLayout, tr("Open URL:"), QString(),
|
||||
s_settings->documentView().openUrl());
|
||||
|
||||
|
||||
m_autoRefreshCheckBox = addCheckBox(m_behaviorLayout, tr("Auto-refresh:"), QString(),
|
||||
s_settings->documentView().autoRefresh());
|
||||
|
||||
|
||||
m_trackRecentlyUsedCheckBox = addCheckBox(m_behaviorLayout, tr("Track recently used:"), tr("Effective after restart."),
|
||||
s_settings->mainWindow().trackRecentlyUsed());
|
||||
|
||||
m_keepRecentlyClosedCheckBox = addCheckBox(m_behaviorLayout, tr("Keep recently closed:"), tr("Effective after restart."),
|
||||
s_settings->mainWindow().keepRecentlyClosed());
|
||||
|
||||
|
||||
m_restoreTabsCheckBox = addCheckBox(m_behaviorLayout, tr("Restore tabs:"), QString(),
|
||||
s_settings->mainWindow().restoreTabs());
|
||||
|
||||
m_restoreBookmarksCheckBox = addCheckBox(m_behaviorLayout, tr("Restore bookmarks:"), QString(),
|
||||
s_settings->mainWindow().restoreBookmarks());
|
||||
|
||||
m_restorePerFileSettingsCheckBox = addCheckBox(m_behaviorLayout, tr("Restore per-file settings:"), QString(),
|
||||
s_settings->mainWindow().restorePerFileSettings());
|
||||
|
||||
m_saveDatabaseInterval = addSpinBox(m_behaviorLayout, tr("Save database interval:"), QString(), tr(" min"), tr("Never"),
|
||||
-1, 60, 1, s_settings->mainWindow().saveDatabaseInterval() / 1000 / 60);
|
||||
|
||||
#ifndef WITH_SQL
|
||||
|
||||
m_restoreTabsCheckBox->setEnabled(false);
|
||||
m_restoreBookmarksCheckBox->setEnabled(false);
|
||||
m_restorePerFileSettingsCheckBox->setEnabled(false);
|
||||
m_saveDatabaseInterval->setEnabled(false);
|
||||
|
||||
#endif // WITH_SQL
|
||||
|
||||
|
||||
m_synchronizePresentationCheckBox = addCheckBox(m_behaviorLayout, tr("Synchronize presentation:"), QString(),
|
||||
s_settings->presentationView().synchronize());
|
||||
|
||||
m_presentationScreenSpinBox = addSpinBox(m_behaviorLayout, tr("Presentation screen:"), QString(), QString(), tr("Default"),
|
||||
-1, QApplication::desktop()->screenCount() - 1, 1, s_settings->presentationView().screen());
|
||||
|
||||
|
||||
m_synchronizeOutlineViewCheckBox = addCheckBox(m_behaviorLayout, tr("Synchronize outline view:"), QString(),
|
||||
s_settings->mainWindow().synchronizeOutlineView());
|
||||
|
||||
m_synchronizeSplitViewsCheckBox = addCheckBox(m_behaviorLayout, tr("Synchronize split views:"), QString(),
|
||||
s_settings->mainWindow().synchronizeSplitViews());
|
||||
|
||||
|
||||
m_minimalScrollingCheckBox = addCheckBox(m_behaviorLayout, tr("Minimal scrolling:"), QString(),
|
||||
s_settings->documentView().minimalScrolling());
|
||||
|
||||
m_zoomFactorSpinBox = addDoubleSpinBox(m_behaviorLayout, tr("Zoom factor:"), QString(), QString(), QString(),
|
||||
1.0, 2.0, 0.05, s_settings->documentView().zoomFactor());
|
||||
|
||||
m_parallelSearchExecutionCheckBox = addCheckBox(m_behaviorLayout, tr("Parallel search execution:"), QString(),
|
||||
s_settings->documentView().parallelSearchExecution());
|
||||
|
||||
|
||||
m_highlightDurationSpinBox = addSpinBox(m_behaviorLayout, tr("Highlight duration:"), QString(), tr(" ms"), tr("None"),
|
||||
0, 60000, 500, s_settings->documentView().highlightDuration());
|
||||
|
||||
m_highlightColorComboBox = addColorComboBox(m_behaviorLayout, tr("Highlight color:"), QString(),
|
||||
s_settings->pageItem().highlightColor());
|
||||
|
||||
m_annotationColorComboBox = addColorComboBox(m_behaviorLayout, tr("Annotation color:"), QString(),
|
||||
s_settings->pageItem().annotationColor());
|
||||
|
||||
|
||||
m_sourceEditorLineEdit = addLineEdit(m_behaviorLayout, tr("Source editor:"), tr("'%1' is replaced by the absolute file path. '%2' resp. '%3' is replaced by line resp. column number."),
|
||||
s_settings->documentView().sourceEditor());
|
||||
}
|
||||
|
||||
void SettingsDialog::acceptBehaivorTab()
|
||||
{
|
||||
s_settings->documentView().setOpenUrl(m_openUrlCheckBox->isChecked());
|
||||
|
||||
s_settings->documentView().setAutoRefresh(m_autoRefreshCheckBox->isChecked());
|
||||
|
||||
s_settings->mainWindow().setTrackRecentlyUsed(m_trackRecentlyUsedCheckBox->isChecked());
|
||||
s_settings->mainWindow().setKeepRecentlyClosed(m_keepRecentlyClosedCheckBox->isChecked());
|
||||
|
||||
s_settings->mainWindow().setRestoreTabs(m_restoreTabsCheckBox->isChecked());
|
||||
s_settings->mainWindow().setRestoreBookmarks(m_restoreBookmarksCheckBox->isChecked());
|
||||
s_settings->mainWindow().setRestorePerFileSettings(m_restorePerFileSettingsCheckBox->isChecked());
|
||||
s_settings->mainWindow().setSaveDatabaseInterval(m_saveDatabaseInterval->value() * 60 * 1000);
|
||||
|
||||
s_settings->presentationView().setSynchronize(m_synchronizePresentationCheckBox->isChecked());
|
||||
s_settings->presentationView().setScreen(m_presentationScreenSpinBox->value());
|
||||
|
||||
s_settings->mainWindow().setSynchronizeOutlineView(m_synchronizeOutlineViewCheckBox->isChecked());
|
||||
s_settings->mainWindow().setSynchronizeSplitViews(m_synchronizeSplitViewsCheckBox->isChecked());
|
||||
|
||||
s_settings->documentView().setMinimalScrolling(m_minimalScrollingCheckBox->isChecked());
|
||||
s_settings->documentView().setZoomFactor(m_zoomFactorSpinBox->value());
|
||||
s_settings->documentView().setParallelSearchExecution(m_parallelSearchExecutionCheckBox->isChecked());
|
||||
|
||||
s_settings->documentView().setHighlightDuration(m_highlightDurationSpinBox->value());
|
||||
s_settings->pageItem().setHighlightColor(validColorFromCurrentText(m_highlightColorComboBox, Defaults::PageItem::highlightColor()));
|
||||
s_settings->pageItem().setAnnotationColor(validColorFromCurrentText(m_annotationColorComboBox, Defaults::PageItem::annotationColor()));
|
||||
|
||||
s_settings->documentView().setSourceEditor(m_sourceEditorLineEdit->text());
|
||||
}
|
||||
|
||||
void SettingsDialog::resetBehaviorTab()
|
||||
{
|
||||
m_openUrlCheckBox->setChecked(Defaults::DocumentView::openUrl());
|
||||
|
||||
m_autoRefreshCheckBox->setChecked(Defaults::DocumentView::autoRefresh());
|
||||
|
||||
m_trackRecentlyUsedCheckBox->setChecked(Defaults::MainWindow::trackRecentlyUsed());
|
||||
m_keepRecentlyClosedCheckBox->setChecked(Defaults::MainWindow::keepRecentlyClosed());
|
||||
|
||||
m_restoreTabsCheckBox->setChecked(Defaults::MainWindow::restoreTabs());
|
||||
m_restoreBookmarksCheckBox->setChecked(Defaults::MainWindow::restoreBookmarks());
|
||||
m_restorePerFileSettingsCheckBox->setChecked(Defaults::MainWindow::restorePerFileSettings());
|
||||
m_saveDatabaseInterval->setValue(Defaults::MainWindow::saveDatabaseInterval());
|
||||
|
||||
m_synchronizePresentationCheckBox->setChecked(Defaults::PresentationView::synchronize());
|
||||
m_presentationScreenSpinBox->setValue(Defaults::PresentationView::screen());
|
||||
|
||||
m_synchronizeOutlineViewCheckBox->setChecked(Defaults::MainWindow::synchronizeOutlineView());
|
||||
m_synchronizeSplitViewsCheckBox->setChecked(Defaults::MainWindow::synchronizeSplitViews());
|
||||
|
||||
m_minimalScrollingCheckBox->setChecked(Defaults::DocumentView::minimalScrolling());
|
||||
m_zoomFactorSpinBox->setValue(Defaults::DocumentView::zoomFactor());
|
||||
m_parallelSearchExecutionCheckBox->setChecked(Defaults::DocumentView::parallelSearchExecution());
|
||||
|
||||
m_highlightDurationSpinBox->setValue(Defaults::DocumentView::highlightDuration());
|
||||
setCurrentTextToColorName(m_highlightColorComboBox, Defaults::PageItem::highlightColor());
|
||||
setCurrentTextToColorName(m_annotationColorComboBox, Defaults::PageItem::annotationColor());
|
||||
|
||||
m_sourceEditorLineEdit->clear();
|
||||
}
|
||||
|
||||
void SettingsDialog::createGraphicsTab()
|
||||
{
|
||||
m_useTilingCheckBox = addCheckBox(m_graphicsLayout, tr("Use tiling:"), QString(),
|
||||
s_settings->pageItem().useTiling());
|
||||
|
||||
m_keepObsoletePixmapsCheckBox = addCheckBox(m_graphicsLayout, tr("Keep obsolete pixmaps:"), QString(),
|
||||
s_settings->pageItem().keepObsoletePixmaps());
|
||||
|
||||
m_useDevicePixelRatioCheckBox = addCheckBox(m_graphicsLayout, tr("Use device pixel ratio:"), QString(),
|
||||
s_settings->pageItem().useDevicePixelRatio());
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,1,0)
|
||||
|
||||
m_useDevicePixelRatioCheckBox->setEnabled(false);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
|
||||
m_decoratePagesCheckBox = addCheckBox(m_graphicsLayout, tr("Decorate pages:"), QString(),
|
||||
s_settings->pageItem().decoratePages());
|
||||
|
||||
m_decorateLinksCheckBox = addCheckBox(m_graphicsLayout, tr("Decorate links:"), QString(),
|
||||
s_settings->pageItem().decorateLinks());
|
||||
|
||||
m_decorateFormFieldsCheckBox = addCheckBox(m_graphicsLayout, tr("Decorate form fields:"), QString(),
|
||||
s_settings->pageItem().decorateFormFields());
|
||||
|
||||
|
||||
m_backgroundColorComboBox = addColorComboBox(m_graphicsLayout, tr("Background color:"), QString(),
|
||||
s_settings->pageItem().backgroundColor());
|
||||
|
||||
m_paperColorComboBox = addColorComboBox(m_graphicsLayout, tr("Paper color:"), QString(),
|
||||
s_settings->pageItem().paperColor());
|
||||
|
||||
m_presentationBackgroundColorComboBox = addColorComboBox(m_graphicsLayout, tr("Presentation background color:"), QString(),
|
||||
s_settings->presentationView().backgroundColor());
|
||||
|
||||
|
||||
m_pagesPerRowSpinBox = addSpinBox(m_graphicsLayout, tr("Pages per row:"), QString(), QString(), QString(),
|
||||
1, 10, 1, s_settings->documentView().pagesPerRow());
|
||||
|
||||
|
||||
m_pageSpacingSpinBox = addDoubleSpinBox(m_graphicsLayout, tr("Page spacing:"), QString(), tr(" px"), QString(),
|
||||
0.0, 25.0, 0.25, s_settings->documentView().pageSpacing());
|
||||
|
||||
m_thumbnailSpacingSpinBox = addDoubleSpinBox(m_graphicsLayout, tr("Thumbnail spacing:"), QString(), tr(" px"), QString(),
|
||||
0.0, 25.0, 0.25, s_settings->documentView().thumbnailSpacing());
|
||||
|
||||
|
||||
m_thumbnailSizeSpinBox = addDoubleSpinBox(m_graphicsLayout, tr("Thumbnail size:"), QString(), tr(" px"), tr("Fit to viewport"),
|
||||
0.0, 1800.0, 25.0, s_settings->documentView().thumbnailSize());
|
||||
|
||||
|
||||
m_cacheSizeComboBox = addDataSizeComboBox(m_graphicsLayout, tr("Cache size:"), QString(),
|
||||
s_settings->pageItem().cacheSize());
|
||||
|
||||
m_prefetchCheckBox = addCheckBox(m_graphicsLayout, tr("Prefetch:"), QString(),
|
||||
s_settings->documentView().prefetch());
|
||||
|
||||
m_prefetchDistanceSpinBox = addSpinBox(m_graphicsLayout, tr("Prefetch distance:"), QString(), QString(), QString(),
|
||||
1, 10, 1, s_settings->documentView().prefetchDistance());
|
||||
}
|
||||
|
||||
void SettingsDialog::acceptGraphicsTab()
|
||||
{
|
||||
s_settings->pageItem().setUseTiling(m_useTilingCheckBox->isChecked());
|
||||
s_settings->pageItem().setKeepObsoletePixmaps(m_keepObsoletePixmapsCheckBox->isChecked());
|
||||
s_settings->pageItem().setUseDevicePixelRatio(m_useDevicePixelRatioCheckBox->isChecked());
|
||||
|
||||
s_settings->pageItem().setDecoratePages(m_decoratePagesCheckBox->isChecked());
|
||||
s_settings->pageItem().setDecorateLinks(m_decorateLinksCheckBox->isChecked());
|
||||
s_settings->pageItem().setDecorateFormFields(m_decorateFormFieldsCheckBox->isChecked());
|
||||
|
||||
s_settings->pageItem().setBackgroundColor(validColorFromCurrentText(m_backgroundColorComboBox, Defaults::PageItem::backgroundColor()));
|
||||
s_settings->pageItem().setPaperColor(validColorFromCurrentText(m_paperColorComboBox, Defaults::PageItem::paperColor()));
|
||||
s_settings->presentationView().setBackgroundColor(validColorFromCurrentText(m_presentationBackgroundColorComboBox, Defaults::PresentationView::backgroundColor()));
|
||||
|
||||
s_settings->documentView().setPagesPerRow(m_pagesPerRowSpinBox->value());
|
||||
|
||||
s_settings->documentView().setPageSpacing(m_pageSpacingSpinBox->value());
|
||||
s_settings->documentView().setThumbnailSpacing(m_thumbnailSpacingSpinBox->value());
|
||||
|
||||
s_settings->documentView().setThumbnailSize(m_thumbnailSizeSpinBox->value());
|
||||
|
||||
s_settings->pageItem().setCacheSize(dataFromCurrentIndex(m_cacheSizeComboBox));
|
||||
s_settings->documentView().setPrefetch(m_prefetchCheckBox->isChecked());
|
||||
s_settings->documentView().setPrefetchDistance(m_prefetchDistanceSpinBox->value());
|
||||
|
||||
if(m_pdfSettingsWidget != 0)
|
||||
{
|
||||
m_pdfSettingsWidget->accept();
|
||||
}
|
||||
|
||||
if(m_psSettingsWidget != 0)
|
||||
{
|
||||
m_psSettingsWidget->accept();
|
||||
}
|
||||
|
||||
if(m_djvuSettingsWidget != 0)
|
||||
{
|
||||
m_djvuSettingsWidget->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::resetGraphicsTab()
|
||||
{
|
||||
m_useTilingCheckBox->setChecked(Defaults::PageItem::useTiling());
|
||||
m_keepObsoletePixmapsCheckBox->setChecked(Defaults::PageItem::keepObsoletePixmaps());
|
||||
m_useDevicePixelRatioCheckBox->setChecked(Defaults::PageItem::useDevicePixelRatio());
|
||||
|
||||
m_decoratePagesCheckBox->setChecked(Defaults::PageItem::decoratePages());
|
||||
m_decorateLinksCheckBox->setChecked(Defaults::PageItem::decorateLinks());
|
||||
m_decorateFormFieldsCheckBox->setChecked(Defaults::PageItem::decorateFormFields());
|
||||
|
||||
setCurrentTextToColorName(m_backgroundColorComboBox, Defaults::PageItem::backgroundColor());
|
||||
setCurrentTextToColorName(m_paperColorComboBox, Defaults::PageItem::paperColor());
|
||||
setCurrentTextToColorName(m_presentationBackgroundColorComboBox, Defaults::PresentationView::backgroundColor());
|
||||
|
||||
m_pagesPerRowSpinBox->setValue(Defaults::DocumentView::pagesPerRow());
|
||||
|
||||
m_pageSpacingSpinBox->setValue(Defaults::DocumentView::pageSpacing());
|
||||
m_thumbnailSpacingSpinBox->setValue(Defaults::DocumentView::thumbnailSpacing());
|
||||
|
||||
m_thumbnailSizeSpinBox->setValue(Defaults::DocumentView::thumbnailSize());
|
||||
|
||||
setCurrentIndexFromData(m_cacheSizeComboBox, Defaults::PageItem::cacheSize());
|
||||
m_prefetchCheckBox->setChecked(Defaults::DocumentView::prefetch());
|
||||
m_prefetchDistanceSpinBox->setValue(Defaults::DocumentView::prefetchDistance());
|
||||
|
||||
if(m_pdfSettingsWidget != 0)
|
||||
{
|
||||
m_pdfSettingsWidget->reset();
|
||||
}
|
||||
|
||||
if(m_psSettingsWidget != 0)
|
||||
{
|
||||
m_psSettingsWidget->reset();
|
||||
}
|
||||
|
||||
if(m_djvuSettingsWidget != 0)
|
||||
{
|
||||
m_djvuSettingsWidget->reset();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsDialog::createInterfaceTab()
|
||||
{
|
||||
m_extendedSearchDock = addCheckBox(m_interfaceLayout, tr("Extended search dock:"), tr("Effective after restart."),
|
||||
s_settings->mainWindow().extendedSearchDock());
|
||||
|
||||
m_annotationOverlayCheckBox = addCheckBox(m_interfaceLayout, tr("Annotation overlay:"), QString(),
|
||||
s_settings->pageItem().annotationOverlay());
|
||||
|
||||
m_formFieldOverlayCheckBox = addCheckBox(m_interfaceLayout, tr("Form field overlay:"), QString(),
|
||||
s_settings->pageItem().formFieldOverlay());
|
||||
|
||||
|
||||
m_tabPositionComboBox = addComboBox(m_interfaceLayout, tr("Tab position:"), QString(),
|
||||
QStringList() << tr("Top") << tr("Bottom") << tr("Left") << tr("Right"),
|
||||
QList< int >() << QTabWidget::North << QTabWidget::South << QTabWidget::West << QTabWidget::East,
|
||||
s_settings->mainWindow().tabPosition());
|
||||
|
||||
m_tabVisibilityComboBox = addComboBox(m_interfaceLayout, tr("Tab visibility:"), QString(),
|
||||
QStringList() << tr("As needed") << tr("Always") << tr("Never"),
|
||||
QList< int >() << TabWidget::TabBarAsNeeded << TabWidget::TabBarAlwaysOn << TabWidget::TabBarAlwaysOff,
|
||||
s_settings->mainWindow().tabVisibility());
|
||||
|
||||
m_spreadTabsCheckBox = addCheckBox(m_interfaceLayout, tr("Spread tabs:"), QString(),
|
||||
s_settings->mainWindow().spreadTabs());
|
||||
|
||||
|
||||
m_newTabNextToCurrentTabCheckBox = addCheckBox(m_interfaceLayout, tr("New tab next to current tab:"), QString(),
|
||||
s_settings->mainWindow().newTabNextToCurrentTab());
|
||||
|
||||
m_exitAfterLastTabCheckBox = addCheckBox(m_interfaceLayout, tr("Exit after last tab:"), QString(),
|
||||
s_settings->mainWindow().exitAfterLastTab());
|
||||
|
||||
|
||||
m_recentlyUsedCountSpinBox = addSpinBox(m_interfaceLayout, tr("Recently used count:"), tr("Effective after restart."), QString(), QString(),
|
||||
1, 50, 1, s_settings->mainWindow().recentlyUsedCount());
|
||||
|
||||
m_recentlyClosedCountSpinBox = addSpinBox(m_interfaceLayout, tr("Recently closed count:"), tr("Effective after restart."), QString(), QString(),
|
||||
1, 25, 1, s_settings->mainWindow().recentlyClosedCount());
|
||||
|
||||
|
||||
m_fileToolBarLineEdit = addLineEdit(m_interfaceLayout, tr("File tool bar:"), tr("Effective after restart."),
|
||||
s_settings->mainWindow().fileToolBar().join(","));
|
||||
|
||||
m_editToolBarLineEdit = addLineEdit(m_interfaceLayout, tr("Edit tool bar:"), tr("Effective after restart."),
|
||||
s_settings->mainWindow().editToolBar().join(","));
|
||||
|
||||
m_viewToolBarLineEdit = addLineEdit(m_interfaceLayout, tr("View tool bar:"), tr("Effective after restart."),
|
||||
s_settings->mainWindow().viewToolBar().join(","));
|
||||
|
||||
m_documentContextMenuLineEdit = addLineEdit(m_interfaceLayout, tr("Document context menu:"), QString(),
|
||||
s_settings->mainWindow().documentContextMenu().join(","));
|
||||
|
||||
m_tabContextMenuLineEdit = addLineEdit(m_interfaceLayout, tr("Tab context menu:"), QString(),
|
||||
s_settings->mainWindow().tabContextMenu().join(","));
|
||||
|
||||
m_scrollableMenusCheckBox = addCheckBox(m_interfaceLayout, tr("Scrollable menus:"), tr("Effective after restart."),
|
||||
s_settings->mainWindow().scrollableMenus());
|
||||
|
||||
m_searchableMenusCheckBox = addCheckBox(m_interfaceLayout, tr("Searchable menus:"), QString(),
|
||||
s_settings->mainWindow().searchableMenus());
|
||||
|
||||
|
||||
m_toggleToolAndMenuBarsWithFullscreenCheckBox = addCheckBox(m_interfaceLayout, tr("Toggle tool and menu bars with fullscreen:"), QString(),
|
||||
s_settings->mainWindow().toggleToolAndMenuBarsWithFullscreen());
|
||||
|
||||
|
||||
m_usePageLabelCheckBox = addCheckBox(m_interfaceLayout, tr("Use page label:"), QString(),
|
||||
s_settings->mainWindow().usePageLabel());
|
||||
|
||||
m_documentTitleAsTabTitleCheckBox = addCheckBox(m_interfaceLayout, tr("Document title as tab title:"), QString(),
|
||||
s_settings->mainWindow().documentTitleAsTabTitle());
|
||||
|
||||
|
||||
m_currentPageInWindowTitleCheckBox = addCheckBox(m_interfaceLayout, tr("Current page in window title:"), QString(),
|
||||
s_settings->mainWindow().currentPageInWindowTitle());
|
||||
|
||||
m_instanceNameInWindowTitleCheckBox = addCheckBox(m_interfaceLayout, tr("Instance name in window title:"), QString(),
|
||||
s_settings->mainWindow().instanceNameInWindowTitle());
|
||||
|
||||
|
||||
m_highlightCurrentThumbnailCheckBox = addCheckBox(m_interfaceLayout, tr("Highlight current thumbnail:"), QString(),
|
||||
s_settings->documentView().highlightCurrentThumbnail());
|
||||
|
||||
m_limitThumbnailsToResultsCheckBox = addCheckBox(m_interfaceLayout, tr("Limit thumbnails to results:"), QString(),
|
||||
s_settings->documentView().limitThumbnailsToResults());
|
||||
}
|
||||
|
||||
void SettingsDialog::acceptInterfaceTab()
|
||||
{
|
||||
s_settings->mainWindow().setExtendedSearchDock(m_extendedSearchDock->isChecked());
|
||||
|
||||
s_settings->pageItem().setAnnotationOverlay(m_annotationOverlayCheckBox->isChecked());
|
||||
s_settings->pageItem().setFormFieldOverlay(m_formFieldOverlayCheckBox);
|
||||
|
||||
s_settings->mainWindow().setTabPosition(dataFromCurrentIndex(m_tabPositionComboBox));
|
||||
s_settings->mainWindow().setTabVisibility(dataFromCurrentIndex(m_tabVisibilityComboBox));
|
||||
s_settings->mainWindow().setSpreadTabs(m_spreadTabsCheckBox->isChecked());
|
||||
|
||||
s_settings->mainWindow().setNewTabNextToCurrentTab(m_newTabNextToCurrentTabCheckBox->isChecked());
|
||||
s_settings->mainWindow().setExitAfterLastTab(m_exitAfterLastTabCheckBox->isChecked());
|
||||
|
||||
s_settings->mainWindow().setRecentlyUsedCount(m_recentlyUsedCountSpinBox->value());
|
||||
s_settings->mainWindow().setRecentlyClosedCount(m_recentlyClosedCountSpinBox->value());
|
||||
|
||||
s_settings->mainWindow().setFileToolBar(m_fileToolBarLineEdit->text().split(",", QString::SkipEmptyParts));
|
||||
s_settings->mainWindow().setEditToolBar(m_editToolBarLineEdit->text().split(",", QString::SkipEmptyParts));
|
||||
s_settings->mainWindow().setViewToolBar(m_viewToolBarLineEdit->text().split(",", QString::SkipEmptyParts));
|
||||
|
||||
s_settings->mainWindow().setDocumentContextMenu(m_documentContextMenuLineEdit->text().split(",", QString::SkipEmptyParts));
|
||||
s_settings->mainWindow().setTabContextMenu(m_tabContextMenuLineEdit->text().split(",", QString::SkipEmptyParts));
|
||||
|
||||
s_settings->mainWindow().setScrollableMenus(m_scrollableMenusCheckBox->isChecked());
|
||||
s_settings->mainWindow().setSearchableMenus(m_searchableMenusCheckBox->isChecked());
|
||||
|
||||
s_settings->mainWindow().setToggleToolAndMenuBarsWithFullscreen(m_toggleToolAndMenuBarsWithFullscreenCheckBox->isChecked());
|
||||
|
||||
s_settings->mainWindow().setUsePageLabel(m_usePageLabelCheckBox->isChecked());
|
||||
s_settings->mainWindow().setDocumentTitleAsTabTitle(m_documentTitleAsTabTitleCheckBox->isChecked());
|
||||
|
||||
s_settings->mainWindow().setCurrentPageInWindowTitle(m_currentPageInWindowTitleCheckBox->isChecked());
|
||||
s_settings->mainWindow().setInstanceNameInWindowTitle(m_instanceNameInWindowTitleCheckBox->isChecked());
|
||||
|
||||
s_settings->documentView().setHighlightCurrentThumbnail(m_highlightCurrentThumbnailCheckBox->isChecked());
|
||||
s_settings->documentView().setLimitThumbnailsToResults(m_limitThumbnailsToResultsCheckBox->isChecked());
|
||||
}
|
||||
|
||||
void SettingsDialog::resetInterfaceTab()
|
||||
{
|
||||
m_extendedSearchDock->setChecked(Defaults::MainWindow::extendedSearchDock());
|
||||
|
||||
m_annotationOverlayCheckBox->setChecked(Defaults::PageItem::annotationOverlay());
|
||||
m_formFieldOverlayCheckBox->setChecked(Defaults::PageItem::formFieldOverlay());
|
||||
|
||||
setCurrentIndexFromData(m_tabPositionComboBox, Defaults::MainWindow::tabPosition());
|
||||
setCurrentIndexFromData(m_tabVisibilityComboBox, Defaults::MainWindow::tabVisibility());
|
||||
m_spreadTabsCheckBox->setChecked(Defaults::MainWindow::spreadTabs());
|
||||
|
||||
m_newTabNextToCurrentTabCheckBox->setChecked(Defaults::MainWindow::newTabNextToCurrentTab());
|
||||
m_exitAfterLastTabCheckBox->setChecked(Defaults::MainWindow::exitAfterLastTab());
|
||||
|
||||
m_recentlyUsedCountSpinBox->setValue(Defaults::MainWindow::recentlyUsedCount());
|
||||
m_recentlyClosedCountSpinBox->setValue(Defaults::MainWindow::recentlyClosedCount());
|
||||
|
||||
m_fileToolBarLineEdit->setText(Defaults::MainWindow::fileToolBar().join(","));
|
||||
m_editToolBarLineEdit->setText(Defaults::MainWindow::editToolBar().join(","));
|
||||
m_viewToolBarLineEdit->setText(Defaults::MainWindow::viewToolBar().join(","));
|
||||
|
||||
m_documentContextMenuLineEdit->setText(Defaults::MainWindow::documentContextMenu().join(","));
|
||||
m_tabContextMenuLineEdit->setText(Defaults::MainWindow::tabContexntMenu().join(","));
|
||||
|
||||
m_scrollableMenusCheckBox->setChecked(Defaults::MainWindow::scrollableMenus());
|
||||
m_searchableMenusCheckBox->setChecked(Defaults::MainWindow::searchableMenus());
|
||||
|
||||
m_toggleToolAndMenuBarsWithFullscreenCheckBox->setChecked(Defaults::MainWindow::toggleToolAndMenuBarsWithFullscreen());
|
||||
|
||||
m_usePageLabelCheckBox->setChecked(Defaults::MainWindow::usePageLabel());
|
||||
m_documentTitleAsTabTitleCheckBox->setChecked(Defaults::MainWindow::documentTitleAsTabTitle());
|
||||
|
||||
m_currentPageInWindowTitleCheckBox->setChecked(Defaults::MainWindow::currentPageInWindowTitle());
|
||||
m_instanceNameInWindowTitleCheckBox->setChecked(Defaults::MainWindow::instanceNameInWindowTitle());
|
||||
|
||||
m_highlightCurrentThumbnailCheckBox->setChecked(Defaults::DocumentView::highlightCurrentThumbnail());
|
||||
m_limitThumbnailsToResultsCheckBox->setChecked(Defaults::DocumentView::limitThumbnailsToResults());
|
||||
}
|
||||
|
||||
void SettingsDialog::createModifiersTab()
|
||||
{
|
||||
m_zoomModifiersComboBox = addModifiersComboBox(m_wheelModifiersLayout, tr("Zoom:"), QString(),
|
||||
s_settings->documentView().zoomModifiers());
|
||||
|
||||
m_rotateModifiersComboBox = addModifiersComboBox(m_wheelModifiersLayout, tr("Rotate:"), QString(),
|
||||
s_settings->documentView().rotateModifiers());
|
||||
|
||||
m_scrollModifiersComboBox = addModifiersComboBox(m_wheelModifiersLayout, tr("Scroll:"), QString(),
|
||||
s_settings->documentView().scrollModifiers());
|
||||
|
||||
m_copyToClipboardModifiersComboBox = addModifiersComboBox(m_buttonModifiersLayout, tr("Copy to clipboard:"), QString(),
|
||||
s_settings->pageItem().copyToClipboardModifiers());
|
||||
|
||||
m_addAnnotationModifiersComboBox = addModifiersComboBox(m_buttonModifiersLayout, tr("Add annotation:"), QString(),
|
||||
s_settings->pageItem().addAnnotationModifiers());
|
||||
|
||||
m_zoomToSelectionModifiersComboBox = addModifiersComboBox(m_buttonModifiersLayout, tr("Zoom to selection:"), QString(),
|
||||
s_settings->pageItem().zoomToSelectionModifiers());
|
||||
|
||||
m_openInSourceEditorModifiersComboBox = addModifiersComboBox(m_buttonModifiersLayout, tr("Open in source editor:"), QString(),
|
||||
s_settings->pageItem().openInSourceEditorModifiers());
|
||||
|
||||
#ifndef WITH_SYNCTEX
|
||||
|
||||
m_openInSourceEditorModifiersComboBox->setEnabled(false);
|
||||
|
||||
#endif // WITH_SYNCTEX
|
||||
}
|
||||
|
||||
void SettingsDialog::acceptModifiersTab()
|
||||
{
|
||||
s_settings->documentView().setZoomModifiers(keyboardModifierFromCurrentIndex(m_zoomModifiersComboBox));
|
||||
s_settings->documentView().setRotateModifiers(keyboardModifierFromCurrentIndex(m_rotateModifiersComboBox));
|
||||
s_settings->documentView().setScrollModifiers(keyboardModifierFromCurrentIndex(m_scrollModifiersComboBox));
|
||||
|
||||
s_settings->pageItem().setCopyToClipboardModifiers(keyboardModifierFromCurrentIndex(m_copyToClipboardModifiersComboBox));
|
||||
s_settings->pageItem().setAddAnnotationModifiers(keyboardModifierFromCurrentIndex(m_addAnnotationModifiersComboBox));
|
||||
s_settings->pageItem().setZoomToSelectionModifiers(keyboardModifierFromCurrentIndex(m_zoomToSelectionModifiersComboBox));
|
||||
s_settings->pageItem().setOpenInSourceEditorModifiers(keyboardModifierFromCurrentIndex(m_openInSourceEditorModifiersComboBox));
|
||||
}
|
||||
|
||||
void SettingsDialog::resetModifiersTab()
|
||||
{
|
||||
setCurrentIndexFromKeyboardModifiers(m_zoomModifiersComboBox, Defaults::DocumentView::zoomModifiers());
|
||||
setCurrentIndexFromKeyboardModifiers(m_rotateModifiersComboBox, Defaults::DocumentView::rotateModifiers());
|
||||
setCurrentIndexFromKeyboardModifiers(m_scrollModifiersComboBox, Defaults::DocumentView::scrollModifiers());
|
||||
|
||||
setCurrentIndexFromKeyboardModifiers(m_copyToClipboardModifiersComboBox, Defaults::PageItem::copyToClipboardModifiers());
|
||||
setCurrentIndexFromKeyboardModifiers(m_addAnnotationModifiersComboBox, Defaults::PageItem::addAnnotationModifiers());
|
||||
setCurrentIndexFromKeyboardModifiers(m_zoomToSelectionModifiersComboBox, Defaults::PageItem::zoomToSelectionModifiers());
|
||||
setCurrentIndexFromKeyboardModifiers(m_openInSourceEditorModifiersComboBox, Defaults::PageItem::openInSourceEditorModifiers());
|
||||
}
|
||||
|
||||
QCheckBox* SettingsDialog::addCheckBox(QFormLayout* layout, const QString& label, const QString& toolTip, bool checked)
|
||||
{
|
||||
QCheckBox* checkBox = new QCheckBox(this);
|
||||
checkBox->setChecked(checked);
|
||||
|
||||
checkBox->setToolTip(toolTip);
|
||||
layout->addRow(label, checkBox);
|
||||
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
QLineEdit* SettingsDialog::addLineEdit(QFormLayout* layout, const QString& label, const QString& toolTip, const QString& text)
|
||||
{
|
||||
QLineEdit* lineEdit = new QLineEdit(this);
|
||||
lineEdit->setText(text);
|
||||
|
||||
lineEdit->setToolTip(toolTip);
|
||||
layout->addRow(label, lineEdit);
|
||||
|
||||
return lineEdit;
|
||||
}
|
||||
|
||||
QSpinBox* SettingsDialog::addSpinBox(QFormLayout* layout, const QString& label, const QString& toolTip, const QString& suffix, const QString& special, int min, int max, int step, int val)
|
||||
{
|
||||
QSpinBox* spinBox = new QSpinBox(this);
|
||||
spinBox->setRange(min, max);
|
||||
spinBox->setSingleStep(step);
|
||||
spinBox->setValue(val);
|
||||
|
||||
spinBox->setSuffix(suffix);
|
||||
spinBox->setSpecialValueText(special);
|
||||
|
||||
spinBox->setToolTip(toolTip);
|
||||
layout->addRow(label, spinBox);
|
||||
|
||||
return spinBox;
|
||||
}
|
||||
|
||||
QDoubleSpinBox* SettingsDialog::addDoubleSpinBox(QFormLayout* layout, const QString& label, const QString& toolTip, const QString& suffix, const QString& special, double min, double max, double step, double val)
|
||||
{
|
||||
QDoubleSpinBox* spinBox = new QDoubleSpinBox(this);
|
||||
spinBox->setRange(min, max);
|
||||
spinBox->setSingleStep(step);
|
||||
spinBox->setValue(val);
|
||||
|
||||
spinBox->setSuffix(suffix);
|
||||
spinBox->setSpecialValueText(special);
|
||||
|
||||
spinBox->setToolTip(toolTip);
|
||||
layout->addRow(label, spinBox);
|
||||
|
||||
return spinBox;
|
||||
}
|
||||
|
||||
QComboBox* SettingsDialog::addComboBox(QFormLayout* layout, const QString& label, const QString& toolTip, const QStringList& text, const QList< int >& data, int value)
|
||||
{
|
||||
QComboBox* comboBox = new QComboBox(this);
|
||||
|
||||
for(int index = 0, count = text.count(); index < count; ++index)
|
||||
{
|
||||
comboBox->addItem(text.at(index), data.at(index));
|
||||
}
|
||||
|
||||
setCurrentIndexFromData(comboBox, value);
|
||||
|
||||
comboBox->setToolTip(toolTip);
|
||||
layout->addRow(label, comboBox);
|
||||
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
QComboBox* SettingsDialog::addDataSizeComboBox(QFormLayout* layout, const QString& label, const QString& toolTip, int initialDataSize)
|
||||
{
|
||||
QComboBox* comboBox = new QComboBox(this);
|
||||
|
||||
for(int dataSize = 8; dataSize <= 8192; dataSize *= 2)
|
||||
{
|
||||
comboBox->addItem(tr("%1 MB").arg(dataSize), dataSize * 1024);
|
||||
}
|
||||
|
||||
int currentIndex = comboBox->findData(initialDataSize);
|
||||
|
||||
if(currentIndex == -1)
|
||||
{
|
||||
currentIndex = comboBox->count();
|
||||
|
||||
comboBox->addItem(tr("%1 MB").arg(initialDataSize / 1024), initialDataSize);
|
||||
}
|
||||
|
||||
comboBox->setCurrentIndex(currentIndex);
|
||||
|
||||
comboBox->setToolTip(toolTip);
|
||||
layout->addRow(label, comboBox);
|
||||
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
QComboBox* SettingsDialog::addColorComboBox(QFormLayout* layout, const QString& label, const QString& toolTip, const QColor& color)
|
||||
{
|
||||
QComboBox* comboBox = new QComboBox(this);
|
||||
comboBox->setEditable(true);
|
||||
comboBox->setInsertPolicy(QComboBox::NoInsert);
|
||||
comboBox->addItems(QColor::colorNames());
|
||||
|
||||
setCurrentTextToColorName(comboBox, color);
|
||||
|
||||
comboBox->setToolTip(toolTip);
|
||||
layout->addRow(label, comboBox);
|
||||
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
QComboBox* SettingsDialog::addModifiersComboBox(QFormLayout* layout, const QString& label, const QString& toolTip, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
QComboBox* comboBox = new QComboBox(this);
|
||||
comboBox->addItem(QShortcut::tr("Shift"), static_cast< int >(Qt::ShiftModifier));
|
||||
comboBox->addItem(QShortcut::tr("Ctrl"), static_cast< int >(Qt::ControlModifier));
|
||||
comboBox->addItem(QShortcut::tr("Alt"), static_cast< int >(Qt::AltModifier));
|
||||
comboBox->addItem(QShortcut::tr("Shift and Ctrl"), static_cast< int >(Qt::ShiftModifier | Qt::ControlModifier));
|
||||
comboBox->addItem(QShortcut::tr("Shift and Alt"), static_cast< int >(Qt::ShiftModifier | Qt::AltModifier));
|
||||
comboBox->addItem(QShortcut::tr("Ctrl and Alt"), static_cast< int >(Qt::ControlModifier | Qt::AltModifier));
|
||||
comboBox->addItem(QShortcut::tr("Right mouse button"), static_cast< int >(Qt::RightButton));
|
||||
comboBox->addItem(QShortcut::tr("Middle mouse button"), static_cast< int >(Qt::MidButton));
|
||||
comboBox->addItem(QShortcut::tr("None"), static_cast< int >(Qt::NoModifier));
|
||||
|
||||
setCurrentIndexFromKeyboardModifiers(comboBox, modifiers);
|
||||
|
||||
comboBox->setToolTip(toolTip);
|
||||
layout->addRow(label, comboBox);
|
||||
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
} // qpdfview
|
222
sources/settingsdialog.h
Parasts fails
222
sources/settingsdialog.h
Parasts fails
@ -0,0 +1,222 @@
|
||||
/*
|
||||
|
||||
Copyright 2015 S. Razi Alavizadeh
|
||||
Copyright 2012-2015 Adam Reichold
|
||||
Copyright 2012 Alexander Volkov
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SETTINGSDIALOG_H
|
||||
#define SETTINGSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class QDialogButtonBox;
|
||||
class QDoubleSpinBox;
|
||||
class QFormLayout;
|
||||
class QGroupBox;
|
||||
class QLineEdit;
|
||||
class QSpinBox;
|
||||
class QTableView;
|
||||
class QTabWidget;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class Settings;
|
||||
class SettingsWidget;
|
||||
|
||||
class SettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsDialog(QWidget* parent = 0);
|
||||
~SettingsDialog();
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
void reset();
|
||||
void resetCurrentTab();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(SettingsDialog)
|
||||
|
||||
static Settings* s_settings;
|
||||
|
||||
QTabWidget* m_graphicsTabWidget;
|
||||
QFormLayout* m_graphicsLayout;
|
||||
|
||||
SettingsWidget* m_pdfSettingsWidget;
|
||||
SettingsWidget* m_psSettingsWidget;
|
||||
SettingsWidget* m_djvuSettingsWidget;
|
||||
|
||||
QTableView* m_shortcutsTableView;
|
||||
|
||||
QTabWidget* m_tabWidget;
|
||||
QDialogButtonBox* m_dialogButtonBox;
|
||||
QPushButton* m_defaultsButton;
|
||||
QPushButton* m_defaultsOnCurrentTabButton;
|
||||
|
||||
QFormLayout* m_behaviorLayout;
|
||||
QFormLayout* m_interfaceLayout;
|
||||
|
||||
QGroupBox* m_wheelModifiersGroupBox;
|
||||
QFormLayout* m_wheelModifiersLayout;
|
||||
|
||||
QGroupBox* m_buttonModifiersGroupBox;
|
||||
QFormLayout* m_buttonModifiersLayout;
|
||||
|
||||
// behavior
|
||||
|
||||
QCheckBox* m_openUrlCheckBox;
|
||||
|
||||
QCheckBox* m_autoRefreshCheckBox;
|
||||
|
||||
QCheckBox* m_trackRecentlyUsedCheckBox;
|
||||
QCheckBox* m_keepRecentlyClosedCheckBox;
|
||||
|
||||
QCheckBox* m_restoreTabsCheckBox;
|
||||
QCheckBox* m_restoreBookmarksCheckBox;
|
||||
QCheckBox* m_restorePerFileSettingsCheckBox;
|
||||
QSpinBox* m_saveDatabaseInterval;
|
||||
|
||||
QCheckBox* m_synchronizePresentationCheckBox;
|
||||
QSpinBox* m_presentationScreenSpinBox;
|
||||
|
||||
QCheckBox* m_synchronizeOutlineViewCheckBox;
|
||||
QCheckBox* m_synchronizeSplitViewsCheckBox;
|
||||
|
||||
QCheckBox* m_minimalScrollingCheckBox;
|
||||
QDoubleSpinBox* m_zoomFactorSpinBox;
|
||||
QCheckBox* m_parallelSearchExecutionCheckBox;
|
||||
|
||||
QSpinBox* m_highlightDurationSpinBox;
|
||||
QComboBox* m_highlightColorComboBox;
|
||||
QComboBox* m_annotationColorComboBox;
|
||||
|
||||
QLineEdit* m_sourceEditorLineEdit;
|
||||
|
||||
void createBehaviorTab();
|
||||
void acceptBehaivorTab();
|
||||
void resetBehaviorTab();
|
||||
|
||||
// graphics
|
||||
|
||||
QCheckBox* m_useTilingCheckBox;
|
||||
QCheckBox* m_keepObsoletePixmapsCheckBox;
|
||||
QCheckBox* m_useDevicePixelRatioCheckBox;
|
||||
|
||||
QCheckBox* m_decoratePagesCheckBox;
|
||||
QCheckBox* m_decorateLinksCheckBox;
|
||||
QCheckBox* m_decorateFormFieldsCheckBox;
|
||||
|
||||
QComboBox* m_backgroundColorComboBox;
|
||||
QComboBox* m_paperColorComboBox;
|
||||
QComboBox* m_presentationBackgroundColorComboBox;
|
||||
|
||||
QSpinBox* m_pagesPerRowSpinBox;
|
||||
|
||||
QDoubleSpinBox* m_pageSpacingSpinBox;
|
||||
QDoubleSpinBox* m_thumbnailSpacingSpinBox;
|
||||
|
||||
QDoubleSpinBox* m_thumbnailSizeSpinBox;
|
||||
|
||||
QComboBox* m_cacheSizeComboBox;
|
||||
QCheckBox* m_prefetchCheckBox;
|
||||
QSpinBox* m_prefetchDistanceSpinBox;
|
||||
|
||||
void createGraphicsTab();
|
||||
void acceptGraphicsTab();
|
||||
void resetGraphicsTab();
|
||||
|
||||
// interface
|
||||
|
||||
QCheckBox* m_extendedSearchDock;
|
||||
|
||||
QCheckBox* m_annotationOverlayCheckBox;
|
||||
QCheckBox* m_formFieldOverlayCheckBox;
|
||||
|
||||
QComboBox* m_tabPositionComboBox;
|
||||
QComboBox* m_tabVisibilityComboBox;
|
||||
QCheckBox* m_spreadTabsCheckBox;
|
||||
|
||||
QCheckBox* m_newTabNextToCurrentTabCheckBox;
|
||||
QCheckBox* m_exitAfterLastTabCheckBox;
|
||||
|
||||
QSpinBox* m_recentlyUsedCountSpinBox;
|
||||
QSpinBox* m_recentlyClosedCountSpinBox;
|
||||
|
||||
QLineEdit* m_fileToolBarLineEdit;
|
||||
QLineEdit* m_editToolBarLineEdit;
|
||||
QLineEdit* m_viewToolBarLineEdit;
|
||||
|
||||
QLineEdit* m_documentContextMenuLineEdit;
|
||||
QLineEdit* m_tabContextMenuLineEdit;
|
||||
|
||||
QCheckBox* m_scrollableMenusCheckBox;
|
||||
QCheckBox* m_searchableMenusCheckBox;
|
||||
|
||||
QCheckBox* m_toggleToolAndMenuBarsWithFullscreenCheckBox;
|
||||
|
||||
QCheckBox* m_usePageLabelCheckBox;
|
||||
QCheckBox* m_documentTitleAsTabTitleCheckBox;
|
||||
|
||||
QCheckBox* m_currentPageInWindowTitleCheckBox;
|
||||
QCheckBox* m_instanceNameInWindowTitleCheckBox;
|
||||
|
||||
QCheckBox* m_highlightCurrentThumbnailCheckBox;
|
||||
QCheckBox* m_limitThumbnailsToResultsCheckBox;
|
||||
|
||||
void createInterfaceTab();
|
||||
void acceptInterfaceTab();
|
||||
void resetInterfaceTab();
|
||||
|
||||
// modifiers
|
||||
|
||||
QComboBox* m_zoomModifiersComboBox;
|
||||
QComboBox* m_rotateModifiersComboBox;
|
||||
QComboBox* m_scrollModifiersComboBox;
|
||||
|
||||
QComboBox* m_copyToClipboardModifiersComboBox;
|
||||
QComboBox* m_addAnnotationModifiersComboBox;
|
||||
QComboBox* m_zoomToSelectionModifiersComboBox;
|
||||
QComboBox* m_openInSourceEditorModifiersComboBox;
|
||||
|
||||
void createModifiersTab();
|
||||
void acceptModifiersTab();
|
||||
void resetModifiersTab();
|
||||
|
||||
// helper methods
|
||||
|
||||
QCheckBox* addCheckBox(QFormLayout* layout, const QString& label, const QString& toolTip, bool checked);
|
||||
QLineEdit* addLineEdit(QFormLayout* layout, const QString& label, const QString& toolTip, const QString& text);
|
||||
QSpinBox* addSpinBox(QFormLayout* layout, const QString& label, const QString& toolTip, const QString& suffix, const QString& special, int min, int max, int step, int val);
|
||||
QDoubleSpinBox* addDoubleSpinBox(QFormLayout* layout, const QString& label, const QString& toolTip, const QString& suffix, const QString& special, double min, double max, double step, double val);
|
||||
QComboBox* addComboBox(QFormLayout* layout, const QString& label, const QString& toolTip, const QStringList& text, const QList< int >& data, int value);
|
||||
QComboBox* addDataSizeComboBox(QFormLayout* layout, const QString& label, const QString& toolTip, int initialDataSize);
|
||||
QComboBox* addColorComboBox(QFormLayout* layout, const QString& label, const QString& toolTip, const QColor& color);
|
||||
QComboBox* addModifiersComboBox(QFormLayout* layout, const QString& label, const QString& toolTip, Qt::KeyboardModifiers modifiers);
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // SETTINGSDIALOG_H
|
297
sources/shortcuthandler.cpp
Parasts fails
297
sources/shortcuthandler.cpp
Parasts fails
@ -0,0 +1,297 @@
|
||||
/*
|
||||
|
||||
Copyright 2013, 2016 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "shortcuthandler.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QSettings>
|
||||
|
||||
#include "documentview.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
QList< QKeySequence > toShortcuts(const QStringList& stringList)
|
||||
{
|
||||
QList< QKeySequence > shortcuts;
|
||||
|
||||
foreach(const QString& string, stringList)
|
||||
{
|
||||
QKeySequence shortcut(string.trimmed());
|
||||
|
||||
if(!shortcut.isEmpty())
|
||||
{
|
||||
shortcuts.append(shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
return shortcuts;
|
||||
}
|
||||
|
||||
QStringList toStringList(const QList< QKeySequence >& shortcuts, QKeySequence::SequenceFormat format = QKeySequence::PortableText)
|
||||
{
|
||||
QStringList stringList;
|
||||
|
||||
foreach(const QKeySequence& shortcut, shortcuts)
|
||||
{
|
||||
stringList.append(shortcut.toString(format));
|
||||
}
|
||||
|
||||
return stringList;
|
||||
}
|
||||
|
||||
inline bool matches(const QKeySequence& keySequence, const QList< QKeySequence >& shortcuts)
|
||||
{
|
||||
foreach(const QKeySequence& shortcut, shortcuts)
|
||||
{
|
||||
if(keySequence.matches(shortcut) == QKeySequence::ExactMatch)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
ShortcutHandler* ShortcutHandler::s_instance = 0;
|
||||
|
||||
ShortcutHandler* ShortcutHandler::instance()
|
||||
{
|
||||
if(s_instance == 0)
|
||||
{
|
||||
s_instance = new ShortcutHandler(qApp);
|
||||
}
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
ShortcutHandler::~ShortcutHandler()
|
||||
{
|
||||
s_instance = 0;
|
||||
}
|
||||
|
||||
void ShortcutHandler::registerAction(QAction* action)
|
||||
{
|
||||
Q_ASSERT(!action->objectName().isEmpty());
|
||||
|
||||
const QList< QKeySequence > defaultShortcuts = action->shortcuts();
|
||||
const QList< QKeySequence > shortcuts = toShortcuts(m_settings->value(action->objectName(), toStringList(defaultShortcuts)).toStringList());
|
||||
|
||||
action->setShortcuts(shortcuts);
|
||||
|
||||
m_actions.append(action);
|
||||
m_shortcuts.insert(action, shortcuts);
|
||||
m_defaultShortcuts.insert(action, defaultShortcuts);
|
||||
}
|
||||
|
||||
int ShortcutHandler::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
int ShortcutHandler::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
|
||||
return m_actions.count();
|
||||
}
|
||||
|
||||
Qt::ItemFlags ShortcutHandler::flags(const QModelIndex& index) const
|
||||
{
|
||||
switch(index.column())
|
||||
{
|
||||
case 0:
|
||||
return Qt::ItemIsEnabled;
|
||||
case 1:
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
return Qt::NoItemFlags;
|
||||
}
|
||||
|
||||
QVariant ShortcutHandler::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
Q_UNUSED(orientation);
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
switch(section)
|
||||
{
|
||||
case 0:
|
||||
return tr("Action");
|
||||
case 1:
|
||||
return tr("Key sequence");
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant ShortcutHandler::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
if((role == Qt::DisplayRole || role == Qt::EditRole) && index.row() >= 0 && index.row() < m_actions.count())
|
||||
{
|
||||
QAction* action = m_actions.at(index.row());
|
||||
|
||||
switch(index.column())
|
||||
{
|
||||
case 0:
|
||||
return action->text().remove(QLatin1Char('&'));
|
||||
case 1:
|
||||
return toStringList(m_shortcuts.value(action), QKeySequence::NativeText).join(";");
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ShortcutHandler::setData(const QModelIndex& index, const QVariant& value, int role)
|
||||
{
|
||||
if(role == Qt::EditRole && index.column() == 1 && index.row() >= 0 && index.row() < m_actions.count())
|
||||
{
|
||||
QList< QKeySequence > shortcuts = toShortcuts(value.toString().split(";", QString::SkipEmptyParts));
|
||||
|
||||
if(!shortcuts.isEmpty() || value.toString().isEmpty())
|
||||
{
|
||||
m_shortcuts.insert(m_actions.at(index.row()), shortcuts);
|
||||
|
||||
emit dataChanged(index, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShortcutHandler::matchesSkipBackward(const QKeySequence& keySequence) const
|
||||
{
|
||||
return matches(keySequence, m_skipBackwardAction->shortcuts());
|
||||
}
|
||||
|
||||
bool ShortcutHandler::matchesSkipForward(const QKeySequence& keySequence) const
|
||||
{
|
||||
return matches(keySequence, m_skipForwardAction->shortcuts());
|
||||
}
|
||||
|
||||
bool ShortcutHandler::matchesMoveUp(const QKeySequence& keySequence) const
|
||||
{
|
||||
return matches(keySequence, m_moveUpAction->shortcuts());
|
||||
}
|
||||
|
||||
bool ShortcutHandler::matchesMoveDown(const QKeySequence& keySequence) const
|
||||
{
|
||||
return matches(keySequence, m_moveDownAction->shortcuts());
|
||||
}
|
||||
|
||||
bool ShortcutHandler::matchesMoveLeft(const QKeySequence& keySequence) const
|
||||
{
|
||||
return matches(keySequence, m_moveLeftAction->shortcuts());
|
||||
}
|
||||
|
||||
bool ShortcutHandler::matchesMoveRight(const QKeySequence& keySequence) const
|
||||
{
|
||||
return matches(keySequence, m_moveRightAction->shortcuts());
|
||||
}
|
||||
|
||||
bool ShortcutHandler::submit()
|
||||
{
|
||||
for(Shortcuts::iterator iterator = m_shortcuts.begin(); iterator != m_shortcuts.end(); ++iterator)
|
||||
{
|
||||
iterator.key()->setShortcuts(iterator.value());
|
||||
}
|
||||
|
||||
foreach(const QAction* action, m_actions)
|
||||
{
|
||||
m_settings->setValue(action->objectName(), toStringList(action->shortcuts()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShortcutHandler::revert()
|
||||
{
|
||||
for(Shortcuts::iterator iterator = m_shortcuts.begin(); iterator != m_shortcuts.end(); ++iterator)
|
||||
{
|
||||
iterator.value() = iterator.key()->shortcuts();
|
||||
}
|
||||
}
|
||||
|
||||
void ShortcutHandler::reset()
|
||||
{
|
||||
for(Shortcuts::iterator iterator = m_defaultShortcuts.begin(); iterator != m_defaultShortcuts.end(); ++iterator)
|
||||
{
|
||||
m_shortcuts.insert(iterator.key(), iterator.value());
|
||||
}
|
||||
|
||||
emit dataChanged(createIndex(0, 1), createIndex(m_actions.count(), 1));
|
||||
}
|
||||
|
||||
ShortcutHandler::ShortcutHandler(QObject* parent) : QAbstractTableModel(parent),
|
||||
m_settings(new QSettings("qpdfview", "shortcuts", this)),
|
||||
m_actions(),
|
||||
m_shortcuts(),
|
||||
m_defaultShortcuts()
|
||||
{
|
||||
m_skipBackwardAction = createAction(
|
||||
tr("Skip backward"), QLatin1String("skipBackward"),
|
||||
QList< QKeySequence >() << QKeySequence(Qt::Key_PageUp) << QKeySequence(Qt::KeypadModifier + Qt::Key_PageUp));
|
||||
|
||||
m_skipForwardAction = createAction(
|
||||
tr("Skip forward"), QLatin1String("skipForward"),
|
||||
QList< QKeySequence >() << QKeySequence(Qt::Key_PageDown) << QKeySequence(Qt::KeypadModifier + Qt::Key_PageDown));
|
||||
|
||||
m_moveUpAction = createAction(
|
||||
tr("Move up"), QLatin1String("moveUp"),
|
||||
QList< QKeySequence >() << QKeySequence(Qt::Key_Up) << QKeySequence(Qt::KeypadModifier + Qt::Key_Up));
|
||||
|
||||
m_moveDownAction = createAction(
|
||||
tr("Move down"), QLatin1String("moveDown"),
|
||||
QList< QKeySequence >() << QKeySequence(Qt::Key_Down) << QKeySequence(Qt::KeypadModifier + Qt::Key_Down));
|
||||
|
||||
m_moveLeftAction = createAction(
|
||||
tr("Move left"), QLatin1String("moveLeft"),
|
||||
QList< QKeySequence >() << QKeySequence(Qt::Key_Left) << QKeySequence(Qt::KeypadModifier + Qt::Key_Left));
|
||||
|
||||
m_moveRightAction = createAction(
|
||||
tr("Move right"), QLatin1String("moveRight"),
|
||||
QList< QKeySequence >() << QKeySequence(Qt::Key_Right) << QKeySequence(Qt::KeypadModifier + Qt::Key_Right));
|
||||
}
|
||||
|
||||
QAction* ShortcutHandler::createAction(const QString& text, const QString& objectName, const QList<QKeySequence>& shortcuts)
|
||||
{
|
||||
QAction* action = new QAction(text, this);
|
||||
action->setObjectName(objectName);
|
||||
action->setShortcuts(shortcuts);
|
||||
|
||||
registerAction(action);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
} // qpdfview
|
96
sources/shortcuthandler.h
Parasts fails
96
sources/shortcuthandler.h
Parasts fails
@ -0,0 +1,96 @@
|
||||
/*
|
||||
|
||||
Copyright 2013, 2016 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SHORTCUTHANDLER_H
|
||||
#define SHORTCUTHANDLER_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QAction>
|
||||
#include <QKeySequence>
|
||||
|
||||
class QSettings;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class ShortcutHandler : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static ShortcutHandler* instance();
|
||||
~ShortcutHandler();
|
||||
|
||||
void registerAction(QAction* action);
|
||||
|
||||
int columnCount(const QModelIndex& parent) const;
|
||||
int rowCount(const QModelIndex& parent) const;
|
||||
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const;
|
||||
bool setData(const QModelIndex& index, const QVariant& value, int role);
|
||||
|
||||
bool matchesSkipBackward(const QKeySequence& keySequence) const;
|
||||
bool matchesSkipForward(const QKeySequence& keySequence) const;
|
||||
|
||||
bool matchesMoveUp(const QKeySequence& keySequence) const;
|
||||
bool matchesMoveDown(const QKeySequence& keySequence) const;
|
||||
bool matchesMoveLeft(const QKeySequence& keySequence) const;
|
||||
bool matchesMoveRight(const QKeySequence& keySequence) const;
|
||||
|
||||
public slots:
|
||||
bool submit();
|
||||
void revert();
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ShortcutHandler)
|
||||
|
||||
static ShortcutHandler* s_instance;
|
||||
ShortcutHandler(QObject* parent = 0);
|
||||
|
||||
QSettings* m_settings;
|
||||
|
||||
QList< QAction* > m_actions;
|
||||
|
||||
typedef QHash< QAction*, QList< QKeySequence > > Shortcuts;
|
||||
Shortcuts m_shortcuts;
|
||||
Shortcuts m_defaultShortcuts;
|
||||
|
||||
QAction* m_skipBackwardAction;
|
||||
QAction* m_skipForwardAction;
|
||||
|
||||
QAction* m_moveUpAction;
|
||||
QAction* m_moveDownAction;
|
||||
QAction* m_moveLeftAction;
|
||||
QAction* m_moveRightAction;
|
||||
|
||||
QAction* createAction(const QString& text, const QString& objectName, const QList< QKeySequence >& shortcuts);
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // SHORTCUTHANDLER_H
|
99
sources/signalhandler.cpp
Parasts fails
99
sources/signalhandler.cpp
Parasts fails
@ -0,0 +1,99 @@
|
||||
/*
|
||||
|
||||
Copyright 2013, 2015 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "signalhandler.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QSocketNotifier>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
int SignalHandler::s_sockets[2];
|
||||
|
||||
bool SignalHandler::prepareSignals()
|
||||
{
|
||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, s_sockets) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
struct sigaction sigAction;
|
||||
|
||||
sigAction.sa_handler = SignalHandler::handleSignals;
|
||||
sigemptyset(&sigAction.sa_mask);
|
||||
sigAction.sa_flags = SA_RESTART;
|
||||
|
||||
if(sigaction(SIGINT, &sigAction, 0) != 0)
|
||||
{
|
||||
close(s_sockets[0]);
|
||||
close(s_sockets[1]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(sigaction(SIGTERM, &sigAction, 0) != 0)
|
||||
{
|
||||
close(s_sockets[0]);
|
||||
close(s_sockets[1]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SignalHandler::SignalHandler(QObject* parent) : QObject(parent),
|
||||
m_socketNotifier(0)
|
||||
{
|
||||
m_socketNotifier = new QSocketNotifier(s_sockets[1], QSocketNotifier::Read, this);
|
||||
connect(m_socketNotifier, SIGNAL(activated(int)), SLOT(on_socketNotifier_activated()));
|
||||
}
|
||||
|
||||
void SignalHandler::on_socketNotifier_activated()
|
||||
{
|
||||
m_socketNotifier->setEnabled(false);
|
||||
|
||||
int sigNumber = 0;
|
||||
Q_UNUSED(read(s_sockets[1], &sigNumber, sizeof(int)));
|
||||
|
||||
switch(sigNumber)
|
||||
{
|
||||
case SIGINT:
|
||||
emit sigIntReceived();
|
||||
break;
|
||||
case SIGTERM:
|
||||
emit sigTermReceived();
|
||||
break;
|
||||
}
|
||||
|
||||
m_socketNotifier->setEnabled(true);
|
||||
}
|
||||
|
||||
void SignalHandler::handleSignals(int sigNumber)
|
||||
{
|
||||
Q_UNUSED(write(s_sockets[0], &sigNumber, sizeof(int)));
|
||||
}
|
||||
|
||||
} // qpdfview
|
61
sources/signalhandler.h
Parasts fails
61
sources/signalhandler.h
Parasts fails
@ -0,0 +1,61 @@
|
||||
/*
|
||||
|
||||
Copyright 2013 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SIGNALHANDLER_H
|
||||
#define SIGNALHANDLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QSocketNotifier;
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class SignalHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static bool prepareSignals();
|
||||
|
||||
explicit SignalHandler(QObject* parent = 0);
|
||||
|
||||
signals:
|
||||
void sigIntReceived();
|
||||
void sigTermReceived();
|
||||
|
||||
private slots:
|
||||
void on_socketNotifier_activated();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(SignalHandler)
|
||||
|
||||
static int s_sockets[2];
|
||||
|
||||
static void handleSignals(int sigNumber);
|
||||
|
||||
QSocketNotifier* m_socketNotifier;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // SIGNALHANDLER_H
|
193
sources/thumbnailitem.cpp
Parasts fails
193
sources/thumbnailitem.cpp
Parasts fails
@ -0,0 +1,193 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "thumbnailitem.h"
|
||||
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <qmath.h>
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
ThumbnailItem::ThumbnailItem(Model::Page* page, const QString& text, int index, QGraphicsItem* parent) : PageItem(page, index, PageItem::ThumbnailMode, parent),
|
||||
m_text(text),
|
||||
m_isHighlighted(false)
|
||||
{
|
||||
setAcceptHoverEvents(false);
|
||||
|
||||
prepareToolTip();
|
||||
}
|
||||
|
||||
QRectF ThumbnailItem::boundingRect() const
|
||||
{
|
||||
return PageItem::boundingRect().adjusted(0.0, 0.0, 0.0, textHeight());
|
||||
}
|
||||
|
||||
void ThumbnailItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
|
||||
{
|
||||
const QRectF boundingRect = PageItem::boundingRect();
|
||||
|
||||
|
||||
painter->save();
|
||||
|
||||
painter->setClipping(true);
|
||||
painter->setClipRect(boundingRect);
|
||||
|
||||
PageItem::paint(painter, option, widget);
|
||||
|
||||
painter->restore();
|
||||
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(4,7,0)
|
||||
|
||||
const QSizeF textSize = m_text.size();
|
||||
|
||||
QPointF pos = boundingRect.bottomLeft();
|
||||
pos.rx() += 0.5 * (boundingRect.width() - textSize.width());
|
||||
pos.ry() += 0.5 * textSize.height();
|
||||
|
||||
painter->drawStaticText(pos, m_text);
|
||||
|
||||
#else
|
||||
|
||||
const QFontMetrics fontMetrics = QFontMetrics(QFont());
|
||||
|
||||
QPointF pos = boundingRect.bottomLeft();
|
||||
pos.rx() += 0.5 * (boundingRect.width() - fontMetrics.width(m_text));
|
||||
pos.ry() += fontMetrics.height();
|
||||
|
||||
painter->drawText(pos, m_text);
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
if(m_isHighlighted)
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->setCompositionMode(QPainter::CompositionMode_Multiply);
|
||||
painter->fillRect(boundingRect, widget->palette().highlight());
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
qreal ThumbnailItem::textHeight() const
|
||||
{
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(4,7,0)
|
||||
|
||||
return 2.0 * m_text.size().height();
|
||||
|
||||
#else
|
||||
|
||||
return 2.0 * QFontMetrics(QFont()).height();
|
||||
|
||||
#endif // QT_VERSION
|
||||
}
|
||||
|
||||
void ThumbnailItem::setHighlighted(bool highlighted)
|
||||
{
|
||||
if(m_isHighlighted != highlighted)
|
||||
{
|
||||
m_isHighlighted = highlighted;
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ThumbnailItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
|
||||
{
|
||||
if(event->modifiers() == Qt::NoModifier
|
||||
&& (event->button() == Qt::LeftButton || event->button() == Qt::MidButton))
|
||||
{
|
||||
emit linkClicked(event->button() == Qt::MidButton, index() + 1);
|
||||
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
|
||||
void ThumbnailItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent*)
|
||||
{
|
||||
}
|
||||
|
||||
void ThumbnailItem::mouseMoveEvent(QGraphicsSceneMouseEvent*)
|
||||
{
|
||||
}
|
||||
|
||||
void ThumbnailItem::mouseReleaseEvent(QGraphicsSceneMouseEvent*)
|
||||
{
|
||||
}
|
||||
|
||||
void ThumbnailItem::contextMenuEvent(QGraphicsSceneContextMenuEvent*)
|
||||
{
|
||||
}
|
||||
|
||||
void ThumbnailItem::prepareToolTip()
|
||||
{
|
||||
const qreal width = size().width() / 72.0 * 25.4;
|
||||
const qreal height = size().height() / 72.0 * 25.4;
|
||||
|
||||
const qreal longEdge = qMax(width, height);
|
||||
const qreal shortEdge = qMin(width, height);
|
||||
|
||||
QString paperSize;
|
||||
|
||||
if(qAbs(longEdge - 279.4) <= 1.0 && qAbs(shortEdge - 215.9) <= 1.0)
|
||||
{
|
||||
paperSize = QLatin1String(" (Letter)");
|
||||
}
|
||||
else
|
||||
{
|
||||
qreal longEdgeA = 1189.0;
|
||||
qreal shortEdgeA = 841.0;
|
||||
|
||||
qreal longEdgeB = 1414.0;
|
||||
qreal shortEdgeB = 1000.0;
|
||||
|
||||
for(int size = 0; size <= 10; ++size)
|
||||
{
|
||||
if(qAbs(longEdge - longEdgeA) <= 1.0 && qAbs(shortEdge - shortEdgeA) <= 1.0)
|
||||
{
|
||||
paperSize = QString(" (A%1)").arg(size);
|
||||
break;
|
||||
}
|
||||
else if(qAbs(longEdge - longEdgeB) <= 1.0 && qAbs(shortEdge - shortEdgeB) <= 1.0)
|
||||
{
|
||||
paperSize = QString(" (B%1)").arg(size);
|
||||
break;
|
||||
}
|
||||
|
||||
longEdgeA = shortEdgeA;
|
||||
shortEdgeA /= qSqrt(2.0);
|
||||
|
||||
longEdgeB = shortEdgeB;
|
||||
shortEdgeB /= qSqrt(2.0);
|
||||
}
|
||||
}
|
||||
|
||||
setToolTip(QString("%1 mm x %2 mm%3").arg(width, 0, 'f', 1).arg(height, 0, 'f', 1).arg(paperSize));
|
||||
}
|
||||
|
||||
} // qpdfview
|
99
sources/thumbnailitem.h
Parasts fails
99
sources/thumbnailitem.h
Parasts fails
@ -0,0 +1,99 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef THUMBNAILITEM_H
|
||||
#define THUMBNAILITEM_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(4,7,0)
|
||||
|
||||
#include <QStaticText>
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
#include "pageitem.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace Model
|
||||
{
|
||||
class Page;
|
||||
}
|
||||
|
||||
class ThumbnailItem : public PageItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ThumbnailItem(Model::Page* page, const QString& text, int index, QGraphicsItem* parent = 0);
|
||||
|
||||
QRectF boundingRect() const;
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(4,7,0)
|
||||
|
||||
QString text() const { return m_text.text(); }
|
||||
void setText(const QString& text) { m_text.setText(text); }
|
||||
|
||||
#else
|
||||
|
||||
const QString& text() const { return m_text; }
|
||||
void setText(const QString& text) { m_text = text; }
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
qreal textHeight() const;
|
||||
|
||||
bool isHighlighted() const { return m_isHighlighted; }
|
||||
void setHighlighted(bool highlighted);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent* event);
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
|
||||
void contextMenuEvent(QGraphicsSceneContextMenuEvent*);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(ThumbnailItem)
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(4,7,0)
|
||||
|
||||
QStaticText m_text;
|
||||
|
||||
#else
|
||||
|
||||
QString m_text;
|
||||
|
||||
#endif // QT_VERSION
|
||||
|
||||
bool m_isHighlighted;
|
||||
|
||||
void prepareToolTip();
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // THUMBNAILITEM_H
|
296
sources/tileitem.cpp
Parasts fails
296
sources/tileitem.cpp
Parasts fails
@ -0,0 +1,296 @@
|
||||
/*
|
||||
|
||||
Copyright 2012-2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "tileitem.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "settings.h"
|
||||
#include "pageitem.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
inline int cacheCost(const QPixmap& pixmap)
|
||||
{
|
||||
return qMax(1, pixmap.width() * pixmap.height() * pixmap.depth() / 8 / 1024);
|
||||
}
|
||||
|
||||
} // anonymous
|
||||
|
||||
Settings* TileItem::s_settings = 0;
|
||||
|
||||
QCache< TileItem::CacheKey, TileItem::CacheObject > TileItem::s_cache;
|
||||
|
||||
TileItem::TileItem(PageItem* page) : RenderTaskParent(),
|
||||
m_page(page),
|
||||
m_rect(),
|
||||
m_cropRect(),
|
||||
m_pixmapError(false),
|
||||
m_pixmap(),
|
||||
m_obsoletePixmap(),
|
||||
m_deleteAfterRender(false),
|
||||
m_renderTask(m_page->m_page, this)
|
||||
{
|
||||
if(s_settings == 0)
|
||||
{
|
||||
s_settings = Settings::instance();
|
||||
}
|
||||
|
||||
s_cache.setMaxCost(s_settings->pageItem().cacheSize());
|
||||
}
|
||||
|
||||
TileItem::~TileItem()
|
||||
{
|
||||
m_renderTask.cancel(true);
|
||||
m_renderTask.wait();
|
||||
}
|
||||
|
||||
void TileItem::setCropRect(const QRectF& cropRect)
|
||||
{
|
||||
if(!m_page->m_renderParam.trimMargins())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_cropRect.isNull() && !cropRect.isNull())
|
||||
{
|
||||
m_cropRect = cropRect;
|
||||
|
||||
m_page->updateCropRect();
|
||||
}
|
||||
}
|
||||
|
||||
void TileItem::dropCachedPixmaps(PageItem* page)
|
||||
{
|
||||
foreach(const CacheKey& key, s_cache.keys())
|
||||
{
|
||||
if(key.first == page)
|
||||
{
|
||||
s_cache.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool TileItem::paint(QPainter* painter, QPointF topLeft)
|
||||
{
|
||||
const QPixmap& pixmap = takePixmap();
|
||||
|
||||
if(!pixmap.isNull())
|
||||
{
|
||||
// pixmap
|
||||
|
||||
painter->drawPixmap(m_rect.topLeft() + topLeft, pixmap);
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(!m_obsoletePixmap.isNull())
|
||||
{
|
||||
// obsolete pixmap
|
||||
|
||||
painter->drawPixmap(QRectF(m_rect).translated(topLeft), m_obsoletePixmap, QRectF());
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const qreal iconExtent = qMin(0.1 * m_rect.width(), 0.1 * m_rect.height());
|
||||
const QRect iconRect(topLeft.x() + m_rect.left() + 0.01 * m_rect.width(),
|
||||
topLeft.y() + m_rect.top() + 0.01 * m_rect.height(),
|
||||
iconExtent, iconExtent);
|
||||
|
||||
if(!m_pixmapError)
|
||||
{
|
||||
// progress icon
|
||||
|
||||
s_settings->pageItem().progressIcon().paint(painter, iconRect);
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// error icon
|
||||
|
||||
s_settings->pageItem().errorIcon().paint(painter, iconRect);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileItem::refresh(bool keepObsoletePixmaps)
|
||||
{
|
||||
if(keepObsoletePixmaps && s_settings->pageItem().keepObsoletePixmaps())
|
||||
{
|
||||
if(const CacheObject* object = s_cache.object(cacheKey()))
|
||||
{
|
||||
m_obsoletePixmap = object->first;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_obsoletePixmap = QPixmap();
|
||||
}
|
||||
|
||||
if(!keepObsoletePixmaps)
|
||||
{
|
||||
m_cropRect = QRectF();
|
||||
}
|
||||
|
||||
m_renderTask.cancel(true);
|
||||
|
||||
m_pixmapError = false;
|
||||
m_pixmap = QPixmap();
|
||||
}
|
||||
|
||||
int TileItem::startRender(bool prefetch)
|
||||
{
|
||||
m_page->startLoadInteractiveElements();
|
||||
|
||||
if(m_pixmapError || m_renderTask.isRunning() || (prefetch && s_cache.contains(cacheKey())))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_renderTask.start(m_page->m_renderParam, m_rect, prefetch);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void TileItem::cancelRender()
|
||||
{
|
||||
m_renderTask.cancel();
|
||||
|
||||
m_pixmap = QPixmap();
|
||||
m_obsoletePixmap = QPixmap();
|
||||
}
|
||||
|
||||
void TileItem::deleteAfterRender()
|
||||
{
|
||||
if(!m_renderTask.isRunning())
|
||||
{
|
||||
m_renderTask.deleteParentLater();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderTask.cancel(true);
|
||||
|
||||
m_deleteAfterRender = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TileItem::on_finished(const RenderParam& renderParam,
|
||||
const QRect& rect, bool prefetch,
|
||||
const QImage& image, const QRectF& cropRect)
|
||||
{
|
||||
if(m_page->m_renderParam != renderParam || m_rect != rect)
|
||||
{
|
||||
on_finishedOrCanceled();
|
||||
return;
|
||||
}
|
||||
|
||||
m_obsoletePixmap = QPixmap();
|
||||
|
||||
if(image.isNull())
|
||||
{
|
||||
m_pixmapError = true;
|
||||
|
||||
on_finishedOrCanceled();
|
||||
return;
|
||||
}
|
||||
|
||||
if(prefetch && !m_renderTask.wasCanceledForcibly())
|
||||
{
|
||||
const QPixmap pixmap = QPixmap::fromImage(image);
|
||||
|
||||
s_cache.insert(cacheKey(), new CacheObject(pixmap, cropRect), cacheCost(pixmap));
|
||||
|
||||
setCropRect(cropRect);
|
||||
}
|
||||
else if(!m_renderTask.wasCanceled())
|
||||
{
|
||||
m_pixmap = QPixmap::fromImage(image);
|
||||
|
||||
setCropRect(cropRect);
|
||||
}
|
||||
|
||||
on_finishedOrCanceled();
|
||||
}
|
||||
|
||||
void TileItem::on_canceled()
|
||||
{
|
||||
on_finishedOrCanceled();
|
||||
}
|
||||
|
||||
void TileItem::on_finishedOrCanceled()
|
||||
{
|
||||
if(m_deleteAfterRender)
|
||||
{
|
||||
m_renderTask.deleteParentLater();
|
||||
}
|
||||
else if(!m_page->useTiling() || m_page->m_exposedTileItems.contains(this))
|
||||
{
|
||||
m_page->update();
|
||||
}
|
||||
}
|
||||
|
||||
inline TileItem::CacheKey TileItem::cacheKey() const
|
||||
{
|
||||
QByteArray key;
|
||||
QDataStream stream(&key, QIODevice::WriteOnly);
|
||||
|
||||
stream << m_page->m_renderParam << m_rect;
|
||||
|
||||
return qMakePair(m_page, key);
|
||||
}
|
||||
|
||||
QPixmap TileItem::takePixmap()
|
||||
{
|
||||
const CacheKey key = cacheKey();
|
||||
|
||||
if(const CacheObject* object = s_cache.object(key))
|
||||
{
|
||||
m_obsoletePixmap = QPixmap();
|
||||
|
||||
setCropRect(object->second);
|
||||
return object->first;
|
||||
}
|
||||
|
||||
QPixmap pixmap;
|
||||
|
||||
if(!m_pixmap.isNull())
|
||||
{
|
||||
s_cache.insert(key, new CacheObject(m_pixmap, m_cropRect), cacheCost(m_pixmap));
|
||||
|
||||
pixmap = m_pixmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
startRender();
|
||||
}
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
} // qpdfview
|
101
sources/tileitem.h
Parasts fails
101
sources/tileitem.h
Parasts fails
@ -0,0 +1,101 @@
|
||||
/*
|
||||
|
||||
Copyright 2014 Adam Reichold
|
||||
|
||||
This file is part of qpdfview.
|
||||
|
||||
qpdfview is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
qpdfview is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with qpdfview. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TILEITEM_H
|
||||
#define TILEITEM_H
|
||||
|
||||
#include <QCache>
|
||||
#include <QObject>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "rendertask.h"
|
||||
|
||||
namespace qpdfview
|
||||
{
|
||||
|
||||
class PageItem;
|
||||
|
||||
class TileItem : public RenderTaskParent
|
||||
{
|
||||
public:
|
||||
TileItem(PageItem* page);
|
||||
~TileItem();
|
||||
|
||||
const QRect& rect() const { return m_rect; }
|
||||
void setRect(QRect rect) { m_rect = rect; }
|
||||
|
||||
const QRectF& cropRect() const { return m_cropRect; }
|
||||
void resetCropRect() { m_cropRect = QRectF(); }
|
||||
void setCropRect(const QRectF& cropRect);
|
||||
|
||||
void dropPixmap() { m_pixmap = QPixmap(); }
|
||||
void dropObsoletePixmap() { m_obsoletePixmap = QPixmap(); }
|
||||
|
||||
static void dropCachedPixmaps(PageItem* page);
|
||||
|
||||
bool paint(QPainter* painter, QPointF topLeft);
|
||||
|
||||
public:
|
||||
void refresh(bool keepObsoletePixmaps = false);
|
||||
|
||||
int startRender(bool prefetch = false);
|
||||
void cancelRender();
|
||||
|
||||
void deleteAfterRender();
|
||||
|
||||
private:
|
||||
void on_finished(const RenderParam& renderParam,
|
||||
const QRect& rect, bool prefetch,
|
||||
const QImage& image, const QRectF& cropRect);
|
||||
void on_canceled();
|
||||
void on_finishedOrCanceled();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(TileItem)
|
||||
|
||||
static Settings* s_settings;
|
||||
|
||||
typedef QPair< PageItem*, QByteArray > CacheKey;
|
||||
typedef QPair< QPixmap, QRectF > CacheObject;
|
||||
|
||||
static QCache< CacheKey, CacheObject > s_cache;
|
||||
|
||||
CacheKey cacheKey() const;
|
||||
|
||||
PageItem* m_page;
|
||||
|
||||
QRect m_rect;
|
||||
QRectF m_cropRect;
|
||||
|
||||
bool m_pixmapError;
|
||||
QPixmap m_pixmap;
|
||||
QPixmap m_obsoletePixmap;
|
||||
|
||||
QPixmap takePixmap();
|
||||
|
||||
bool m_deleteAfterRender;
|
||||
RenderTask m_renderTask;
|
||||
|
||||
};
|
||||
|
||||
} // qpdfview
|
||||
|
||||
#endif // PAGEITEM_H
|
Atsaukties uz šo jaunā problēmā
Block a user