aboutsummaryrefslogtreecommitdiff
path: root/src/Remember.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Remember.cc')
-rw-r--r--src/Remember.cc140
1 files changed, 121 insertions, 19 deletions
diff --git a/src/Remember.cc b/src/Remember.cc
index c134741..b90a252 100644
--- a/src/Remember.cc
+++ b/src/Remember.cc
@@ -36,6 +36,7 @@
36 36
37#include "FbTk/I18n.hh" 37#include "FbTk/I18n.hh"
38#include "FbTk/StringUtil.hh" 38#include "FbTk/StringUtil.hh"
39#include "FbTk/FileUtil.hh"
39#include "FbTk/MenuItem.hh" 40#include "FbTk/MenuItem.hh"
40#include "FbTk/App.hh" 41#include "FbTk/App.hh"
41#include "FbTk/stringstream.hh" 42#include "FbTk/stringstream.hh"
@@ -230,13 +231,16 @@ Application::Application(bool grouped)
230 231
231Remember *Remember::s_instance = 0; 232Remember *Remember::s_instance = 0;
232 233
233Remember::Remember() { 234Remember::Remember():
235 m_pats(new Patterns()),
236 m_last_timestamp(0)
237{
234 if (s_instance != 0) 238 if (s_instance != 0)
235 throw string("Can not create more than one instance of Remember"); 239 throw string("Can not create more than one instance of Remember");
236 240
237 s_instance = this; 241 s_instance = this;
238 enableUpdate(); 242 enableUpdate();
239 load(); 243 reconfigure();
240} 244}
241 245
242Remember::~Remember() { 246Remember::~Remember() {
@@ -247,11 +251,11 @@ Remember::~Remember() {
247 // the client mapping shouldn't need cleaning 251 // the client mapping shouldn't need cleaning
248 Patterns::iterator it; 252 Patterns::iterator it;
249 std::set<Application *> all_apps; // no duplicates 253 std::set<Application *> all_apps; // no duplicates
250 while (!m_pats.empty()) { 254 while (!m_pats->empty()) {
251 it = m_pats.begin(); 255 it = m_pats->begin();
252 delete it->first; // ClientPattern 256 delete it->first; // ClientPattern
253 all_apps.insert(it->second); // Application, not necessarily unique 257 all_apps.insert(it->second); // Application, not necessarily unique
254 m_pats.erase(it); 258 m_pats->erase(it);
255 } 259 }
256 260
257 std::set<Application *>::iterator ait = all_apps.begin(); // no duplicates 261 std::set<Application *>::iterator ait = all_apps.begin(); // no duplicates
@@ -270,8 +274,8 @@ Application* Remember::find(WinClient &winclient) {
270 if (wc_it != m_clients.end()) 274 if (wc_it != m_clients.end())
271 return wc_it->second; 275 return wc_it->second;
272 else { 276 else {
273 Patterns::iterator it = m_pats.begin(); 277 Patterns::iterator it = m_pats->begin();
274 for (; it != m_pats.end(); it++) 278 for (; it != m_pats->end(); it++)
275 if (it->first->match(winclient)) { 279 if (it->first->match(winclient)) {
276 it->first->addMatch(); 280 it->first->addMatch();
277 m_clients[&winclient] = it->second; 281 m_clients[&winclient] = it->second;
@@ -289,7 +293,7 @@ Application * Remember::add(WinClient &winclient) {
289 p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME); 293 p->addTerm(p->getProperty(ClientPattern::NAME, winclient), ClientPattern::NAME);
290 m_clients[&winclient] = app; 294 m_clients[&winclient] = app;
291 p->addMatch(); 295 p->addMatch();
292 m_pats.push_back(make_pair(p, app)); 296 m_pats->push_back(make_pair(p, app));
293 return app; 297 return app;
294} 298}
295 299
@@ -463,16 +467,66 @@ int Remember::parseApp(ifstream &file, Application &app, string *first_line) {
463 return row; 467 return row;
464} 468}
465 469
466void Remember::load() { 470/*
471 This function is used to search for old instances of the same pattern
472 (when reloading apps file). More than one pattern might match, but only
473 if the application is the same (also note that they'll be adjacent).
474 We REMOVE and delete any matching patterns from the old list, as they're
475 effectively moved into the new
476*/
477
478Application *Remember::findMatchingPatterns(ClientPattern *pat, Patterns *patlist, bool is_group) {
479 Patterns::iterator it = patlist->begin();
480 Patterns::iterator it_end = patlist->end();
481 for (; it != it_end; ++it) {
482 if (it->first->equals(*pat) && is_group == it->second->is_grouped) {
483 Application *ret = it->second;
484
485 // find any previous or subsequent matching ones and delete
486
487 // rewind
488 Patterns::iterator tmpit = it;
489 while (tmpit != patlist->begin()) {
490 --tmpit;
491 if (tmpit->second == ret)
492 it = tmpit;
493 else
494 break;
495 }
496
497 // forward
498 while (it != it_end && it->second == ret) {
499 tmpit = it;
500 ++it;
501 delete tmpit->first;
502 patlist->erase(tmpit);
503 }
504 return ret;
505 }
506 }
467 507
508 return 0;
509}
510
511
512void Remember::reconfigure() {
468 string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename()); 513 string apps_string = FbTk::StringUtil::expandFilename(Fluxbox::instance()->getAppsFilename());
469 514
515 time_t timestamp = FbTk::FileUtil::getLastStatusChangeTimestamp(apps_string.c_str());
516 if (m_last_timestamp > 0 && m_last_timestamp == timestamp)
517 return;
518
470#ifdef DEBUG 519#ifdef DEBUG
471 cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<<apps_string<<"]"<<endl; 520 cerr<<__FILE__<<"("<<__FUNCTION__<<"): Loading apps file ["<<apps_string<<"]"<<endl;
472#endif // DEBUG 521#endif // DEBUG
473 ifstream apps_file(apps_string.c_str()); 522 ifstream apps_file(apps_string.c_str());
474 523
524 // we merge the old patterns with new ones
525 Patterns *old_pats = m_pats.release();
526 m_pats.reset(new Patterns());
527
475 if (!apps_file.fail()) { 528 if (!apps_file.fail()) {
529 m_last_timestamp = timestamp;
476 if (!apps_file.eof()) { 530 if (!apps_file.eof()) {
477 string line; 531 string line;
478 int row = 0; 532 int row = 0;
@@ -494,8 +548,11 @@ void Remember::load() {
494 ClientPattern *pat = new ClientPattern(line.c_str() + pos); 548 ClientPattern *pat = new ClientPattern(line.c_str() + pos);
495 if (!in_group) { 549 if (!in_group) {
496 if ((err = pat->error()) == 0) { 550 if ((err = pat->error()) == 0) {
497 Application *app = new Application(false); 551 Application *app = findMatchingPatterns(pat, old_pats, false);
498 m_pats.push_back(make_pair(pat, app)); 552 if (!app)
553 app = new Application(false);
554
555 m_pats->push_back(make_pair(pat, app));
499 row += parseApp(apps_file, *app); 556 row += parseApp(apps_file, *app);
500 } else { 557 } else {
501 cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl; 558 cerr<<"Error reading apps file at line "<<row<<", column "<<(err+pos)<<"."<<endl;
@@ -514,10 +571,21 @@ void Remember::load() {
514 in_group = true; 571 in_group = true;
515 } else if (in_group) { 572 } else if (in_group) {
516 // otherwise assume that it is the start of the attributes 573 // otherwise assume that it is the start of the attributes
517 Application *app = new Application(true); 574 Application *app = 0;
575 // search for a matching app
576 std::list<ClientPattern *>::iterator it = grouped_pats.begin();
577 std::list<ClientPattern *>::iterator it_end = grouped_pats.end();
578 while (!app && it != it_end) {
579 app = findMatchingPatterns(*it, old_pats, true);
580 ++it;
581 }
582
583 if (!app)
584 app = new Application(true);
585
518 while (!grouped_pats.empty()) { 586 while (!grouped_pats.empty()) {
519 // associate all the patterns with this app 587 // associate all the patterns with this app
520 m_pats.push_back(make_pair(grouped_pats.front(), app)); 588 m_pats->push_back(make_pair(grouped_pats.front(), app));
521 grouped_pats.pop_front(); 589 grouped_pats.pop_front();
522 } 590 }
523 591
@@ -540,6 +608,40 @@ void Remember::load() {
540 } else { 608 } else {
541 cerr << "apps file failure" << endl; 609 cerr << "apps file failure" << endl;
542 } 610 }
611
612 // Clean up old state
613 // can't just delete old patterns list. Need to delete the
614 // patterns themselves, plus the applications!
615
616 Patterns::iterator it;
617 std::set<Application *> old_apps; // no duplicates
618 while (!old_pats->empty()) {
619 it = old_pats->begin();
620 delete it->first; // ClientPattern
621 old_apps.insert(it->second); // Application, not necessarily unique
622 old_pats->erase(it);
623 }
624
625 // now remove any client entries for the old apps
626 Clients::iterator cit = m_clients.begin();
627 Clients::iterator cit_end = m_clients.end();
628 while (cit != cit_end) {
629 if (old_apps.find(cit->second) != old_apps.end()) {
630 Clients::iterator tmpit = cit;
631 ++cit;
632 m_clients.erase(tmpit);
633 } else {
634 ++cit;
635 }
636 }
637
638 std::set<Application *>::iterator ait = old_apps.begin(); // no duplicates
639 while (ait != old_apps.end()) {
640 delete (*ait);
641 ++ait;
642 }
643
644 delete old_pats;
543} 645}
544 646
545void Remember::save() { 647void Remember::save() {
@@ -558,8 +660,8 @@ void Remember::save() {
558 apps_file<<"[startup] "<<(*sit)<<endl; 660 apps_file<<"[startup] "<<(*sit)<<endl;
559 } 661 }
560 662
561 Patterns::iterator it = m_pats.begin(); 663 Patterns::iterator it = m_pats->begin();
562 Patterns::iterator it_end = m_pats.end(); 664 Patterns::iterator it_end = m_pats->end();
563 665
564 std::set<Application *> grouped_apps; // no duplicates 666 std::set<Application *> grouped_apps; // no duplicates
565 667
@@ -572,8 +674,8 @@ void Remember::save() {
572 grouped_apps.insert(&a); 674 grouped_apps.insert(&a);
573 // otherwise output this whole group 675 // otherwise output this whole group
574 apps_file << "[group]" << endl; 676 apps_file << "[group]" << endl;
575 Patterns::iterator git = m_pats.begin(); 677 Patterns::iterator git = m_pats->begin();
576 Patterns::iterator git_end = m_pats.end(); 678 Patterns::iterator git_end = m_pats->end();
577 for (; git != git_end; git++) { 679 for (; git != git_end; git++) {
578 if (git->second == &a) { 680 if (git->second == &a) {
579 apps_file << " [app]"<<git->first->toString()<<endl; 681 apps_file << " [app]"<<git->first->toString()<<endl;
@@ -969,8 +1071,8 @@ void Remember::initForScreen(BScreen &screen) {
969 1071
970void Remember::updateFrameClose(FluxboxWindow &win) { 1072void Remember::updateFrameClose(FluxboxWindow &win) {
971 // scan all applications and remove this fbw if it is a recorded group 1073 // scan all applications and remove this fbw if it is a recorded group
972 Patterns::iterator it = m_pats.begin(); 1074 Patterns::iterator it = m_pats->begin();
973 while (it != m_pats.end()) { 1075 while (it != m_pats->end()) {
974 if (&win == it->second->group) 1076 if (&win == it->second->group)
975 it->second->group = 0; 1077 it->second->group = 0;
976 ++it; 1078 ++it;