Commit 1b69086d authored by Philipp Erhardt's avatar Philipp Erhardt
Browse files

Implement searching backwards

parent 8a466883
......@@ -91,9 +91,11 @@ KEY BINDINGS
*[*, *]* ::
Adjust column count ('grid layout' only).
*/* ::
Show search bar. Hitting *Esc* will hide the results, searching for an
Show the search bar. Hitting *Esc* will hide the results, searching for an
empty string will clear them. If the search term contains an uppercase
letter the search is case sensitive ("smartcase").
*?* ::
Show the search bar. This next search will be backwards.
*n*, *N* ::
Focus next/previous search hit.
*\^n*, *^N* ::
......
......@@ -40,6 +40,7 @@ columns_dec=[
toggle_overlay=T
quit=Q, "W,E,E,E"
search=/
search_backward=?
next_hit=N
previous_hit=Shift+N
next_invisible_hit=Ctrl+N
......
......@@ -59,6 +59,7 @@ CFG::CFG() :
keys["toggle_overlay"] = QStringList() << "T";
keys["quit"] = QStringList() << "Q" << "W,E,E,E";
keys["search"] = QStringList() << "/";
keys["search_backward"] = QStringList() << "?";
keys["next_hit"] = QStringList() << "N";
keys["previous_hit"] = QStringList() << "Shift+N";
keys["next_invisible_hit"] = QStringList() << "Ctrl+N";
......
......@@ -106,19 +106,34 @@ bool Layout::scroll_page(int new_page, bool relative) {
void Layout::update_search() {
const map<int,QList<QRectF> *> *hits = viewer->get_search_bar()->get_hits();
if (hits->empty()) {
return;
}
// find the right page before/after the current one
map<int,QList<QRectF> *>::const_iterator it = hits->lower_bound(page);
if (it != hits->end()) {
hit_page = it->first;
hit_it = hits->find(hit_page)->second->begin();
view_hit();
bool forward = viewer->get_search_bar()->is_search_forward();
if (forward) {
if (it == hits->end()) {
it = hits->lower_bound(0);
}
} else {
if (hits->size() == 1) {
hit_page = hits->lower_bound(0)->first;
hit_it = hits->find(hit_page)->second->begin();
view_hit();
if (it->first != page) {
if (it == hits->begin()) {
it = hits->end();
}
--it;
}
}
hit_page = it->first;
if (forward) {
hit_it = it->second->begin();
} else {
hit_it = it->second->end();
--hit_it;
}
view_hit();
}
void Layout::set_search_visible(bool visible) {
......@@ -132,7 +147,7 @@ bool Layout::advance_hit(bool forward) {
return false;
}
// find next hit
if (forward) {
if (forward ^ !viewer->get_search_bar()->is_search_forward()) {
++hit_it;
if (hit_it == hits->find(hit_page)->second->end()) {
// this was the last hit on hit_page
......
......@@ -144,7 +144,7 @@ bool PresentationLayout::advance_invisible_hit(bool forward) {
return false;
}
if (forward) {
if (forward ^ !viewer->get_search_bar()->is_search_forward()) {
hit_it = hits->find(hit_page)->second->end();
--hit_it;
} else {
......
......@@ -224,7 +224,7 @@ bool PresenterLayout::advance_invisible_hit(bool forward) {
return false;
}
if (forward) {
if (forward ^ !viewer->get_search_bar()->is_search_forward()) {
hit_it = hits->find(hit_page)->second->end();
--hit_it;
} else {
......
......@@ -14,7 +14,8 @@ using namespace std;
SearchWorker::SearchWorker(SearchBar *_bar) :
stop(false),
die(false),
bar(_bar) {
bar(_bar),
forward(true) {
}
void SearchWorker::run() {
......@@ -36,6 +37,7 @@ void SearchWorker::run() {
}
int start = bar->start_page;
QString search_term = bar->term;
forward = bar->forward;
bar->term_mutex.unlock();
// check if term contains upper case letters; if so, do case sensitive search (smartcase)
......@@ -101,16 +103,27 @@ void SearchWorker::run() {
}
// update progress label next to the search bar
int percent = ((page + bar->doc->numPages() - start)
% bar->doc->numPages()) * 100 / bar->doc->numPages();
int percent;
if (forward) {
percent = page + bar->doc->numPages() - start;
} else {
percent = start + bar->doc->numPages() - page;
}
percent = (percent % bar->doc->numPages()) * 100 / bar->doc->numPages();
QString progress = QString("[%1] %2\% searched, %3 hits")
.arg(has_upper_case ? "Case" : "no case")
.arg(percent)
.arg(hit_count);
emit update_label_text(progress);
if (++page == bar->doc->numPages()) {
page = 0;
if (forward) {
if (++page == bar->doc->numPages()) {
page = 0;
}
} else {
if (--page == -1) {
page = bar->doc->numPages() - 1;
}
}
} while (page != start);
#ifdef DEBUG
......@@ -199,7 +212,8 @@ bool SearchBar::is_valid() const {
return doc != NULL;
}
void SearchBar::focus() {
void SearchBar::focus(bool forward) {
forward_tmp = forward; // only apply when the user presses enter
line->activateWindow();
line->setText(term);
line->setFocus(Qt::OtherFocusReason);
......@@ -211,6 +225,10 @@ const std::map<int,QList<QRectF> *> *SearchBar::get_hits() const {
return &hits;
}
bool SearchBar::is_search_forward() const {
return forward;
}
bool SearchBar::event(QEvent *event) {
if (event->type() == QEvent::Hide) {
viewer->get_canvas()->set_search_visible(false);
......@@ -261,6 +279,7 @@ void SearchBar::set_text() {
return;
}
forward = forward_tmp;
Canvas *c = viewer->get_canvas();
// do not start the same search again but signal slots
if (term == line->text()) {
......
......@@ -36,6 +36,7 @@ signals:
private:
SearchBar *bar;
bool forward;
};
......@@ -48,8 +49,9 @@ public:
void load(const QString &file, const QByteArray &password);
bool is_valid() const;
void focus();
void focus(bool forward = true);
const std::map<int,QList<QRectF> *> *get_hits() const;
bool is_search_forward() const;
signals:
void search_updated(int page);
......@@ -85,6 +87,8 @@ private:
SearchWorker *worker;
QString term;
int start_page;
bool forward_tmp;
bool forward;
friend class SearchWorker;
};
......
......@@ -345,6 +345,10 @@ void Viewer::search() {
search_bar->focus();
}
void Viewer::search_backward() {
search_bar->focus(false);
}
void Viewer::next_hit() {
if (canvas->get_layout()->get_search_visible()) {
int page = canvas->get_layout()->get_page();
......@@ -510,6 +514,7 @@ void Viewer::setup_keys(QWidget *base) {
add_action(base, "columns_dec", SLOT(columns_dec()));
add_action(base, "quit", SLOT(quit()));
add_action(base, "search", SLOT(search()));
add_action(base, "search_backward", SLOT(search_backward()));
add_action(base, "next_hit", SLOT(next_hit()));
add_action(base, "previous_hit", SLOT(previous_hit()));
add_action(base, "next_invisible_hit", SLOT(next_invisible_hit()));
......
......@@ -59,6 +59,7 @@ private slots:
void columns_dec();
void quit();
void search();
void search_backward();
void next_hit();
void previous_hit();
void next_invisible_hit();
......
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