qpdfview 0.4.18.tar.gz release, cc642e7fa74029373ca9b9fbc29adc4883f8b455130a78ad54746d6844a0396c

Šī revīzija ir iekļauta:
2019-11-15 20:31:02 +01:00
revīzija 0bbe0da55e
221 mainīti faili ar 156020 papildinājumiem un 0 dzēšanām

187
sources/annotationwidgets.cpp Parasts fails
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

108
sources/database.h Parasts fails
Parādīt failu

@ -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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

140
sources/djvumodel.h Parasts fails
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

390
sources/documentview.h Parasts fails
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

587
sources/mainwindow.h Parasts fails
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

228
sources/pageitem.h Parasts fails
Parādīt failu

@ -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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

267
sources/pdfmodel.h Parasts fails
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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

Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

706
sources/settings.h Parasts fails
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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
Parādīt failu

@ -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