Viewer::Viewer(const QString &file, QWidget *parent) : QWidget(parent), res(NULL), splitter(NULL), toc(NULL), canvas(NULL), search_bar(NULL), layout(NULL), sig_notifier(NULL), beamer(NULL), valid(true) { res = new ResourceManager(file, this); if (!res->is_valid()) { if (CFG::get_instance()->get_most_current_value("Settings/quit_on_init_fail").toBool()) { valid = false; return; } } search_bar = new SearchBar(file, this, this); if (!search_bar->is_valid()) { if (CFG::get_instance()->get_most_current_value("Settings/quit_on_init_fail").toBool()) { valid = false; return; } } // 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()), Qt::UniqueConnection); 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; } setup_keys(this); beamer = new BeamerWindow(this); setup_keys(beamer); splitter = new Splitter(this); toc = new Toc(this, splitter); canvas = new Canvas(this, splitter); // beamer must already exist if (!canvas->is_valid()) { valid = false; return; } res->connect_canvas(); canvas->update_page_overlay(); // set initial position splitter->addWidget(toc); splitter->addWidget(canvas); splitter->setSizes(QList<int>() << (width() / 4) << (width() * 3 / 4)); // TODO config option toc->hide(); // load config options CFG *config = CFG::get_instance(); smooth_scroll_delta = config->get_value("Settings/smooth_scroll_delta").toInt(); screen_scroll_factor = config->get_value("Settings/screen_scroll_factor").toFloat(); layout = new QVBoxLayout(); layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); // initialize info bar QIcon::setThemeName(CFG::get_instance()->get_value("Settings/icon_theme").toString()); info_label_icon.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); info_password.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); info_widget.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); info_label_text.setWordWrap(true); info_label_text.setTextFormat(Qt::PlainText); info_password.setEchoMode(QLineEdit::Password); info_layout.addWidget(&info_label_icon); info_layout.addWidget(&info_label_text); info_layout.addWidget(&info_password); info_widget.setLayout(&info_layout); layout->addWidget(&info_widget); connect(&info_password, SIGNAL(returnPressed()), this, SLOT(reload()), Qt::UniqueConnection); update_info_widget(); presenter_progress.setMinimum(1); presenter_progress.setMaximum(res->get_page_count()); presenter_progress.setValue(canvas->get_layout()->get_page() + 1); // presenter_progress.setFormat("%v/%m"); presenter_progress.setTextVisible(true); layout->addWidget(splitter); layout->addWidget(&presenter_progress); layout->addWidget(search_bar); setLayout(layout); QFileInfo info(res->get_file()); setWindowTitle(QString::fromUtf8("%1 \u2014 katarakt").arg(info.fileName())); setMinimumSize(50, 50); resize(500, 500); search_bar->hide(); info_password.setFocus(Qt::OtherFocusReason); // only works if shown // apply start options if (res->is_valid()) { canvas->get_layout()->scroll_page(config->get_tmp_value("start_page").toInt(), false); } if (CFG::get_instance()->get_tmp_value("fullscreen").toBool()) { toggle_fullscreen(); } // enable transparency, but only in the right places setAttribute(Qt::WA_TranslucentBackground); presenter_progress.setAutoFillBackground(true); search_bar->setAutoFillBackground(true); info_widget.setAutoFillBackground(true); toc->setAutoFillBackground(true); // the splitter handle has to be opaque, canvas has to be transparent // problem: either both are transparent or none is // these functions don't help, the splitter handle is still transparent (depending on theme) // splitter->handle(0)->setAttribute(Qt::WA_TranslucentBackground, false); // splitter->handle(0)->setBackgroundRole(QPalette::Window); // splitter->handle(0)->setAutoFillBackground(true); }
Canvas::Canvas(Viewer *v, QWidget *parent) : QWidget(parent), viewer(v), triple_click_possible(false), valid(true) { setFocusPolicy(Qt::StrongFocus); // load config options CFG *config = CFG::get_instance(); { bool ok; unsigned int color = config->get_value("Settings/background_color").toString().toUInt(&ok, 16); if (ok) { background.setRgba(color); } else { cerr << "failed to parse background_color" << endl; } } { bool ok; unsigned int color = config->get_value("Settings/background_color_fullscreen").toString().toUInt(&ok, 16); if (ok) { background_fullscreen.setRgba(color); } else { cerr << "failed to parse background_color_fullscreen" << endl; } } mouse_wheel_factor = config->get_value("Settings/mouse_wheel_factor").toInt(); switch (config->get_value("Settings/click_link_button").toInt()) { case 1: click_link_button = Qt::LeftButton; break; case 2: click_link_button = Qt::RightButton; break; case 3: click_link_button = Qt::MidButton; break; case 4: click_link_button = Qt::XButton1; break; case 5: click_link_button = Qt::XButton2; break; default: click_link_button = Qt::NoButton; } switch (config->get_value("Settings/drag_view_button").toInt()) { case 1: drag_view_button = Qt::LeftButton; break; case 2: drag_view_button = Qt::RightButton; break; case 3: drag_view_button = Qt::MidButton; break; case 4: drag_view_button = Qt::XButton1; break; case 5: drag_view_button = Qt::XButton2; break; default: drag_view_button = Qt::NoButton; } switch (config->get_value("Settings/select_text_button").toInt()) { case 1: select_text_button = Qt::LeftButton; break; case 2: select_text_button = Qt::RightButton; break; case 3: select_text_button = Qt::MidButton; break; case 4: select_text_button = Qt::XButton1; break; case 5: select_text_button = Qt::XButton2; break; default: select_text_button = Qt::NoButton; } single_layout = new SingleLayout(viewer, 0); grid_layout = new GridLayout(viewer, 0); presenter_layout = new PresenterLayout(viewer, 1); QString default_layout = config->get_value("Settings/default_layout").toString(); if (default_layout == "grid") { cur_layout = grid_layout; } else if (default_layout == "presenter") { cur_layout = presenter_layout; } else { // "single" and everything else cur_layout = single_layout; } setup_keys(this); if (drag_view_button == Qt::LeftButton) { setCursor(Qt::OpenHandCursor); } else { setCursor(Qt::IBeamCursor); } // prints the string representation of a key // cerr << QKeySequence(Qt::Key_Equal).toString().toUtf8().constData() << endl; goto_line = new GotoLine(viewer->get_res()->get_page_count(), this); goto_line->move(0, height() - goto_line->height()); // TODO goto_line->height() reports the wrong size goto_line->hide(); connect(goto_line, SIGNAL(returnPressed()), this, SLOT(goto_page()), Qt::UniqueConnection); page_overlay = new QLabel(this); page_overlay->setMargin(1); page_overlay->setAutoFillBackground(true); page_overlay->show(); // setup beamer BeamerWindow *beamer = viewer->get_beamer(); setup_keys(beamer); if (cur_layout == presenter_layout) { beamer->show(); viewer->show_progress(true); } else { beamer->hide(); viewer->show_progress(false); } }