Commit f37ce5ab authored by Philipp Erhardt's avatar Philipp Erhardt
Browse files

refactor

make Viewer the central class
some minor changes (includes, const, ...)
parent c019978e
#include "canvas.h"
#include <csignal>
#include <cstring>
#include <cerrno>
#include <unistd.h>
#include "viewer.h"
#include "layout.h"
#include "resourcemanager.h"
using namespace std;
int Canvas::sig_fd[2];
Canvas::Canvas(ResourceManager *_res, QWidget *parent) :
Canvas::Canvas(Viewer *v, QWidget *parent) :
QWidget(parent),
res(_res),
viewer(v),
draw_overlay(true),
valid(true) {
setFocusPolicy(Qt::StrongFocus);
res->set_canvas(this);
layout = new PresentationLayout(res);
// setup signal handling
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sig_fd) == -1) {
cerr << "socketpair: " << strerror(errno) << endl;
valid = false;
sig_notifier = NULL;
return;
}
sig_notifier = new QSocketNotifier(sig_fd[1], QSocketNotifier::Read, this);
connect(sig_notifier, SIGNAL(activated(int)), this, SLOT(handle_signal()));
struct sigaction usr;
usr.sa_handler = Canvas::signal_handler;
sigemptyset(&usr.sa_mask);
usr.sa_flags = SA_RESTART;
if (sigaction(SIGUSR1, &usr, 0) > 0) {
cerr << "sigaction: " << strerror(errno) << endl;
valid = false;
return;
}
layout = new PresentationLayout(viewer->get_res());
// prints the string representation of a key
// cerr << QKeySequence(Qt::Key_Equal).toString().toUtf8().constData() << endl;
......@@ -74,7 +48,6 @@ Canvas::Canvas(ResourceManager *_res, QWidget *parent) :
add_sequence("[", &Canvas::columns_dec);
add_sequence("T", &Canvas::toggle_overlay);
add_sequence("R", &Canvas::reload);
add_sequence("Q", &Canvas::quit);
add_sequence("n,0,0,b", &Canvas::quit); // just messing around :)
......@@ -83,9 +56,6 @@ Canvas::Canvas(ResourceManager *_res, QWidget *parent) :
}
Canvas::~Canvas() {
::close(sig_fd[0]);
::close(sig_fd[1]);
delete sig_notifier;
delete layout;
}
......@@ -93,23 +63,9 @@ bool Canvas::is_valid() const {
return valid;
}
void Canvas::signal_handler(int /*unused*/) {
char tmp = '1';
if (write(sig_fd[0], &tmp, sizeof(char)) < 0) {
cerr << "write: " << strerror(errno) << endl;
}
}
void Canvas::handle_signal() {
sig_notifier->setEnabled(false);
char tmp;
if (read(sig_fd[1], &tmp, sizeof(char)) < 0) {
cerr << "read: " << strerror(errno) << endl;
}
reload();
sig_notifier->setEnabled(true);
void Canvas::reload() {
layout->rebuild();
update();
}
void Canvas::add_sequence(QString key, func_t action) {
......@@ -137,7 +93,7 @@ void Canvas::paintEvent(QPaintEvent * /*event*/) {
QString title = QString("page %1/%2")
.arg(layout->get_page() + 1)
.arg(res->get_page_count());
.arg(viewer->get_res()->get_page_count());
if (draw_overlay) {
QRect size = QRect(0, 0, width(), height());
......@@ -216,7 +172,7 @@ void Canvas::page_first() {
}
void Canvas::page_last() {
layout->scroll_page(res->get_page_count(), false);
layout->scroll_page(viewer->get_res()->get_page_count(), false);
update();
}
......@@ -287,12 +243,6 @@ void Canvas::toggle_overlay() {
update();
}
void Canvas::reload() {
res->reload_document();
layout->rebuild();
update();
}
void Canvas::quit() {
QCoreApplication::exit(0);
}
......
......@@ -12,16 +12,13 @@
#include <QCoreApplication>
#include <QResizeEvent>
#include <QKeySequence>
#include <QSocketNotifier>
#include <iostream>
#include <map>
#include <sys/socket.h>
#include "resourcemanager.h"
#include "layout.h"
class Canvas;
class Viewer;
class Layout;
class Canvas : public QWidget {
......@@ -30,14 +27,11 @@ class Canvas : public QWidget {
typedef void (Canvas::*func_t)();
public:
Canvas(ResourceManager *res, QWidget *parent = 0);
Canvas(Viewer *v, QWidget *parent = 0);
~Canvas();
bool is_valid() const;
// signal handling
static void signal_handler(int unused);
public slots:
void handle_signal();
void reload();
protected:
// QT event handling
......@@ -73,13 +67,12 @@ private:
void columns_inc();
void columns_dec();
void toggle_overlay();
void reload();
void quit();
void search();
void add_sequence(QString key, func_t action);
ResourceManager *res;
Viewer *viewer;
Layout *layout;
// key sequences
......@@ -89,9 +82,6 @@ private:
bool draw_overlay;
// signal handling
static int sig_fd[2];
QSocketNotifier *sig_notifier;
bool valid;
};
......
#include "grid.h"
//#include <cstring>
#include "resourcemanager.h"
#include <iostream>
using namespace std;
......
#ifndef GRID_H
#define GRID_H
#include "resourcemanager.h"
class ResourceManager;
class Grid {
......
#include "layout.h"
#include "resourcemanager.h"
#include "grid.h"
using namespace std;
......@@ -41,7 +43,7 @@ void Layout::set_columns(int /*new_columns*/, bool /*relative*/) {
// only useful for grid layout
}
bool Layout::supports_smooth_scrolling() {
bool Layout::supports_smooth_scrolling() const {
// normally a layout supports smooth scrolling
return true;
}
......@@ -75,7 +77,7 @@ PresentationLayout::PresentationLayout(Layout& old_layout) :
Layout(old_layout) {
}
bool PresentationLayout::supports_smooth_scrolling() {
bool PresentationLayout::supports_smooth_scrolling() const {
return false;
}
......
#ifndef LAYOUT_H
#define LAYOUT_H
#include <iostream>
#include <QPainter>
#include <QImage>
#include "resourcemanager.h"
#include "grid.h"
class ResourceManager;
class Grid;
class Layout {
......@@ -21,7 +21,7 @@ public:
virtual void set_zoom(int new_zoom, bool relative = true);
virtual void set_columns(int new_columns, bool relative = true);
virtual bool supports_smooth_scrolling();
virtual bool supports_smooth_scrolling() const;
virtual void scroll_smooth(int dx, int dy);
virtual void scroll_page(int new_page, bool relative = true);
virtual void render(QPainter *painter) = 0;
......@@ -40,7 +40,7 @@ public:
PresentationLayout(Layout& old_layout);
~PresentationLayout() {};
bool supports_smooth_scrolling();
bool supports_smooth_scrolling() const;
void scroll_smooth(int dx, int dy);
void render(QPainter *painter);
......
#include <QApplication>
#include <QImage>
#include <QString>
#include <QPalette>
#include <iostream>
#include "resourcemanager.h"
#include "viewer.h"
int main(int argc, char *argv[]) {
using namespace std;
QApplication app(argc, argv);
// app.setPalette(QPalette(QColor(255, 255, 255), QColor(0, 0, 0)));
if (argc != 2) {
cerr << "usage: " << argv[0] << " <path>" << endl;
return 1;
}
ResourceManager res(QString::fromUtf8(argv[1]));
if (!res.is_valid()) {
return 1;
}
Viewer katarakt(&res);
Viewer katarakt(QString::fromUtf8(argv[1]));
if (!katarakt.is_valid()) {
return 1;
}
katarakt.show();
return app.exec();
}
......
#include "resourcemanager.h"
#include "canvas.h"
#include <iostream>
using namespace std;
......@@ -12,8 +13,8 @@ Worker::Worker() :
die(false) {
}
void Worker::setResManager(ResourceManager *rm) {
res = rm;
void Worker::setResManager(ResourceManager *_res) {
res = _res;
}
void Worker::connect_signal(Canvas *c) {
......@@ -82,13 +83,12 @@ void Worker::run() {
//==[ ResourceManager ]========================================================
ResourceManager::ResourceManager(QString _file) :
worker(NULL),
file(_file) {
initialize();
ResourceManager::ResourceManager(QString file) :
worker(NULL) {
initialize(file);
}
void ResourceManager::initialize() {
void ResourceManager::initialize(QString file) {
doc = Poppler::Document::load(file);
if (doc == NULL) {
// poppler already prints a debug message
......@@ -104,7 +104,7 @@ void ResourceManager::initialize() {
doc->setRenderHint(Poppler::Document::Antialiasing, true);
doc->setRenderHint(Poppler::Document::TextAntialiasing, true);
doc->setRenderHint(Poppler::Document::TextHinting, true);
// if (POPPLER_CHECK_VERSION(0, 18, 0)) {
// if (POPPLER_CHECK_VERSION(0, 18, 0)) { // TODO is there a working macro?
doc->setRenderHint(Poppler::Document::TextSlightHinting, true);
// }
......@@ -152,6 +152,7 @@ void ResourceManager::shutdown() {
garbage.clear();
garbageMutex.unlock();
requests.clear();
requestSemaphore.acquire(requestSemaphore.available());
if (doc == NULL) {
return;
}
......@@ -164,27 +165,16 @@ void ResourceManager::shutdown() {
delete worker;
}
void ResourceManager::reload_document() {
void ResourceManager::load(QString file) {
shutdown();
requests.clear();
#ifdef DEBUG
cerr << "reloading file " << file.toUtf8().constData() << endl;
#endif
requestSemaphore.acquire(requestSemaphore.available());
initialize();
set_canvas(canvas);
}
QString ResourceManager::get_file() const {
return file;
initialize(file);
}
bool ResourceManager::is_valid() const {
return (doc != NULL);
}
void ResourceManager::set_canvas(Canvas *c) {
canvas = c;
void ResourceManager::connect_canvas(Canvas *c) const {
worker->connect_signal(c);
}
......
......@@ -7,7 +7,6 @@
#include <QThread>
#include <QMutex>
#include <QSemaphore>
#include <iostream>
#include <list>
#include <set>
#include <utility>
......@@ -23,7 +22,7 @@ class Worker : public QThread {
public:
Worker();
void setResManager(ResourceManager *res);
void setResManager(ResourceManager *_res);
void connect_signal(Canvas *c);
void run();
......@@ -39,11 +38,10 @@ private:
class ResourceManager {
public:
ResourceManager(QString _file);
ResourceManager(QString file);
~ResourceManager();
void reload_document();
QString get_file() const;
void load(QString file);
// document opened correctly?
bool is_valid() const;
......@@ -59,20 +57,19 @@ public:
void collect_garbage(int keep_min, int keep_max);
void set_canvas(Canvas *c);
void connect_canvas(Canvas *c) const;
private:
void enqueue(int page, int width);
bool render(int offset);
void initialize();
void initialize(QString file);
void join_threads();
void shutdown();
// sadly, poppler's renderToImage only supports one thread per document
Worker *worker;
QString file;
Poppler::Document *doc;
QMutex *imgMutex;
QMutex requestMutex;
......@@ -87,7 +84,6 @@ private:
friend class Worker;
float *page_width, *page_height;
Canvas *canvas;
};
#endif
......
#include "viewer.h"
#include "resourcemanager.h"
#include "canvas.h"
#include <iostream>
#include <QFileInfo>
#include <csignal>
#include <cerrno>
#include <unistd.h>
using namespace std;
Viewer::Viewer(ResourceManager *res, QWidget *parent) :
int Viewer::sig_fd[2];
//Viewer::Viewer(ResourceManager *res, QWidget *parent) :
Viewer::Viewer(QString _file, QWidget *parent) :
QWidget(parent),
file(_file),
res(NULL),
canvas(NULL),
search_bar(NULL),
layout(NULL),
sig_notifier(NULL),
valid(true) {
canvas = new Canvas(res, this);
res = new ResourceManager(file);
if (!res->is_valid()) {
valid = false;
return;
}
canvas = new Canvas(this, this);
if (!canvas->is_valid()) {
valid = false;
search_bar = NULL;
layout = NULL;
return;
}
res->connect_canvas(canvas);
search_bar = new QLineEdit(this);
// setup signal handling
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sig_fd) == -1) {
cerr << "socketpair: " << strerror(errno) << endl;
valid = false;
return;
}
sig_notifier = new QSocketNotifier(sig_fd[1], QSocketNotifier::Read, this);
connect(sig_notifier, SIGNAL(activated(int)), this, SLOT(signal_slot()));
struct sigaction usr;
usr.sa_handler = Viewer::signal_handler;
sigemptyset(&usr.sa_mask);
usr.sa_flags = SA_RESTART;
if (sigaction(SIGUSR1, &usr, 0) > 0) {
cerr << "sigaction: " << strerror(errno) << endl;
valid = false;
return;
}
// TODO these sequences conflict between widgets
add_sequence("F", &Viewer::toggle_fullscreen);
add_sequence("Esc", &Viewer::close_search);
add_sequence("R", &Viewer::reload);
layout = new QVBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
......@@ -25,7 +69,7 @@ Viewer::Viewer(ResourceManager *res, QWidget *parent) :
layout->addWidget(search_bar);
setLayout(layout);
QFileInfo info(res->get_file());
QFileInfo info(file);
setWindowTitle(QString::fromUtf8("%1 \u2014 katarakt").arg(info.fileName()));
setMinimumSize(50, 50);
resize(500, 500);
......@@ -34,9 +78,13 @@ Viewer::Viewer(ResourceManager *res, QWidget *parent) :
}
Viewer::~Viewer() {
::close(sig_fd[0]);
::close(sig_fd[1]);
delete sig_notifier;
delete layout;
delete search_bar;
delete canvas;
delete res;
}
bool Viewer::is_valid() const {
......@@ -49,6 +97,42 @@ void Viewer::focus_search() {
search_bar->show();
}
void Viewer::reload() {
#ifdef DEBUG
cerr << "reloading file " << file.toUtf8().constData() << endl;
#endif
res->load(file);
res->connect_canvas(canvas);
canvas->reload();
}
ResourceManager *Viewer::get_res() const {
return res;
}
Canvas *Viewer::get_canvas() const {
return canvas;
}
void Viewer::signal_slot() {
sig_notifier->setEnabled(false);
char tmp;
if (read(sig_fd[1], &tmp, sizeof(char)) < 0) {
cerr << "read: " << strerror(errno) << endl;
}
reload();
sig_notifier->setEnabled(true);
}
void Viewer::signal_handler(int /*unused*/) {
char tmp = '1';
if (write(sig_fd[0], &tmp, sizeof(char)) < 0) {
cerr << "write: " << strerror(errno) << endl;
}
}
void Viewer::toggle_fullscreen() {
setWindowState(windowState() ^ Qt::WindowFullScreen);
}
......
......@@ -5,11 +5,13 @@
#include <QVBoxLayout>
#include <QLineEdit>
#include <QKeySequence>
#include "canvas.h"
#include <QSocketNotifier>
#include <map>
class ResourceManager;
class Canvas;
class Viewer : public QWidget {
Q_OBJECT
......@@ -17,12 +19,21 @@ class Viewer : public QWidget {
typedef void (Viewer::*func_t)();
public:
Viewer(ResourceManager *res, QWidget *parent = 0);
// Viewer(ResourceManager *res, QWidget *parent = 0);
Viewer(QString _file, QWidget *parent = 0);
~Viewer();
bool is_valid() const;
void focus_search();
void reload();
ResourceManager *get_res() const;
Canvas *get_canvas() const;
public slots:
void signal_slot();
protected:
bool event(QEvent *event);
......@@ -31,9 +42,16 @@ private:
void close_search();
void add_sequence(QString key, func_t action);
QVBoxLayout *layout;
QLineEdit *search_bar;
QString file;
ResourceManager *res;
Canvas *canvas;
QLineEdit *search_bar;
QVBoxLayout *layout;
// signal handling
static void signal_handler(int unused);
static int sig_fd[2];
QSocketNotifier *sig_notifier;
// key sequences
std::map<QKeySequence,func_t> sequences;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment