Date: | 2015-04-23 21:07:33 (8 years 7 months ago) |
---|---|
Author: | Maarten ter Huurne |
Commit: | 7eb377a8578d44365073179c54e6ee155cb73f33 |
Message: | Keep track of Link objects using unique_ptr This ensures the memory is freed when the pointers are removed. While there was an explicit delete loop in the destructor, memory leaks could occur when links were removed from the menu. |
Files: |
src/menu.cpp (16 diffs) src/menu.h (3 diffs) |
Change Details
src/menu.cpp | ||
---|---|---|
104 | 104 | btnContextMenu.setPosition(gmenu2x.resX - 38, gmenu2x.bottomBarIconY); |
105 | 105 | } |
106 | 106 | |
107 | Menu::~Menu() { | |
108 | freeLinks(); | |
107 | Menu::~Menu() | |
108 | { | |
109 | 109 | } |
110 | 110 | |
111 | 111 | void Menu::readSections(std::string const& parentDir) |
... | ... | |
151 | 151 | linkRows = (gmenu2x.resY - 35 - skinConfInt["topBarHeight"]) / skinConfInt["linkHeight"]; |
152 | 152 | |
153 | 153 | //reload section icons |
154 | vector<string>::size_type i = 0; | |
155 | for (string sectionName : sections) { | |
154 | decltype(links)::size_type i = 0; | |
155 | for (auto& sectionName : sections) { | |
156 | 156 | gmenu2x.sc["skin:sections/" + sectionName + ".png"]; |
157 | 157 | |
158 | for (Link *&link : links[i]) { | |
158 | for (auto& link : links[i]) { | |
159 | 159 | link->loadIcon(); |
160 | 160 | } |
161 | 161 | |
... | ... | |
233 | 233 | sc.skinRes("imgs/section-l.png")->blit(s, 0, 0); |
234 | 234 | sc.skinRes("imgs/section-r.png")->blit(s, width - 10, 0); |
235 | 235 | |
236 | vector<Link*> §ionLinks = links[iSection]; | |
237 | const uint numLinks = sectionLinks.size(); | |
236 | auto& sectionLinks = links[iSection]; | |
237 | auto numLinks = sectionLinks.size(); | |
238 | 238 | gmenu2x.drawScrollBar( |
239 | 239 | linkRows, (numLinks + linkColumns - 1) / linkColumns, iFirstDispRow); |
240 | 240 | |
... | ... | |
353 | 353 | /*==================================== |
354 | 354 | SECTION MANAGEMENT |
355 | 355 | ====================================*/ |
356 | void Menu::freeLinks() { | |
357 | for (vector< vector<Link*> >::iterator section = links.begin(); section<links.end(); section++) | |
358 | for (vector<Link*>::iterator link = section->begin(); link<section->end(); link++) | |
359 | delete *link; | |
360 | } | |
361 | 356 | |
362 | vector<Link*> *Menu::sectionLinks(int i) { | |
363 | if (i<0 || i>=(int)links.size()) | |
357 | vector<unique_ptr<Link>> *Menu::sectionLinks(int i) | |
358 | { | |
359 | if (i<0 || i>=(int)links.size()) { | |
364 | 360 | i = selSectionIndex(); |
361 | } | |
365 | 362 | |
366 | if (i<0 || i>=(int)links.size()) | |
367 | return NULL; | |
363 | if (i<0 || i>=(int)links.size()) { | |
364 | return nullptr; | |
365 | } | |
368 | 366 | |
369 | 367 | return &links[i]; |
370 | 368 | } |
... | ... | |
417 | 415 | link->setIcon(icon); |
418 | 416 | } |
419 | 417 | |
420 | links[section].push_back(link); | |
418 | links[section].emplace_back(link); | |
421 | 419 | } |
422 | 420 | |
423 | 421 | bool Menu::addLink(string const& path, string const& file) |
... | ... | |
501 | 499 | auto idx = sectionNamed(sectionName); |
502 | 500 | auto link = new LinkApp(gmenu2x, linkpath, true); |
503 | 501 | link->setSize(gmenu2x.skinConfInt["linkWidth"], gmenu2x.skinConfInt["linkHeight"]); |
504 | links[idx].push_back(link); | |
502 | links[idx].emplace_back(link); | |
505 | 503 | } else { |
506 | 504 | |
507 | 505 | ERROR("Error while opening the file '%s' for write.\n", linkpath.c_str()); |
... | ... | |
525 | 523 | |
526 | 524 | void Menu::deleteSelectedLink() |
527 | 525 | { |
528 | bool icon_used = false; | |
529 | 526 | string iconpath = selLink()->getIconPath(); |
530 | 527 | |
531 | 528 | INFO("Deleting link '%s'\n", selLink()->getTitle().c_str()); |
... | ... | |
535 | 532 | sectionLinks()->erase( sectionLinks()->begin() + selLinkIndex() ); |
536 | 533 | setLinkIndex(selLinkIndex()); |
537 | 534 | |
538 | for (vector< vector<Link*> >::iterator section = links.begin(); | |
539 | !icon_used && section<links.end(); section++) | |
540 | for (vector<Link*>::iterator link = section->begin(); | |
541 | !icon_used && link<section->end(); link++) | |
542 | icon_used = iconpath == (*link)->getIconPath(); | |
543 | ||
544 | if (!icon_used) | |
545 | gmenu2x.sc.del(iconpath); | |
535 | bool icon_used = false; | |
536 | for (auto& section : links) { | |
537 | for (auto& link : section) { | |
538 | if (iconpath == link->getIconPath()) { | |
539 | icon_used = true; | |
540 | } | |
541 | } | |
542 | } | |
543 | if (!icon_used) { | |
544 | gmenu2x.sc.del(iconpath); | |
545 | } | |
546 | 546 | } |
547 | 547 | |
548 | 548 | void Menu::deleteSelectedSection() { |
... | ... | |
555 | 555 | } |
556 | 556 | |
557 | 557 | bool Menu::linkChangeSection(uint linkIndex, uint oldSectionIndex, uint newSectionIndex) { |
558 | if (oldSectionIndex<sections.size() && newSectionIndex<sections.size() && linkIndex<sectionLinks(oldSectionIndex)->size()) { | |
559 | sectionLinks(newSectionIndex)->push_back( sectionLinks(oldSectionIndex)->at(linkIndex) ); | |
560 | sectionLinks(oldSectionIndex)->erase( sectionLinks(oldSectionIndex)->begin()+linkIndex ); | |
561 | //Select the same link in the new position | |
562 | setSectionIndex(newSectionIndex); | |
563 | setLinkIndex(sectionLinks(newSectionIndex)->size()-1); | |
564 | return true; | |
565 | } | |
566 | return false; | |
558 | // Fetch sections. | |
559 | auto oldSectionLinks = sectionLinks(oldSectionIndex); | |
560 | if (!oldSectionLinks) return false; | |
561 | auto newSectionLinks = sectionLinks(newSectionIndex); | |
562 | if (!newSectionLinks) return false; | |
563 | ||
564 | // Find link in old section. | |
565 | if (linkIndex >= oldSectionLinks->size()) return false; | |
566 | auto it = oldSectionLinks->begin() + linkIndex; | |
567 | ||
568 | // Move link. | |
569 | auto link = it->release(); | |
570 | oldSectionLinks->erase(it); | |
571 | newSectionLinks->emplace_back(link); | |
572 | ||
573 | // Select the same link in the new section. | |
574 | setSectionIndex(newSectionIndex); | |
575 | setLinkIndex(newSectionLinks->size() - 1); | |
576 | ||
577 | return true; | |
567 | 578 | } |
568 | 579 | |
569 | 580 | void Menu::linkLeft() { |
... | ... | |
615 | 626 | } |
616 | 627 | |
617 | 628 | Link *Menu::selLink() { |
618 | if (sectionLinks()->size()==0) return NULL; | |
619 | return sectionLinks()->at(iLink); | |
629 | auto curSectionLinks = sectionLinks(); | |
630 | if (curSectionLinks->empty()) { | |
631 | return nullptr; | |
632 | } else { | |
633 | return curSectionLinks->at(iLink).get(); | |
634 | } | |
620 | 635 | } |
621 | 636 | |
622 | 637 | LinkApp *Menu::selLinkApp() { |
... | ... | |
705 | 720 | link->setSize(gmenu2x.skinConfInt["linkWidth"], gmenu2x.skinConfInt["linkHeight"]); |
706 | 721 | |
707 | 722 | auto idx = sectionNamed(link->getCategory()); |
708 | links[idx].push_back(link); | |
723 | links[idx].emplace_back(link); | |
709 | 724 | } |
710 | 725 | |
711 | 726 | opk_close(opk); |
... | ... | |
753 | 768 | * correspond to an OPK present in the directory. */ |
754 | 769 | void Menu::removePackageLink(std::string const& path) |
755 | 770 | { |
756 | for (vector< vector<Link*> >::iterator section = links.begin(); | |
757 | section < links.end(); section++) { | |
758 | for (vector<Link*>::iterator link = section->begin(); | |
759 | link < section->end(); link++) { | |
760 | LinkApp *app = dynamic_cast<LinkApp *> (*link); | |
771 | for (auto section = links.begin(); section != links.end(); ++section) { | |
772 | for (auto link = section->begin(); link != section->end(); ++link) { | |
773 | LinkApp *app = dynamic_cast<LinkApp *>(link->get()); | |
761 | 774 | if (!app || !app->isOpk() || app->getOpkFile().empty()) |
762 | 775 | continue; |
763 | 776 | |
... | ... | |
766 | 779 | app->getOpkFile().c_str()); |
767 | 780 | section->erase(link); |
768 | 781 | if (section - links.begin() == iSection |
769 | && iLink == (int) section->size()) | |
782 | && iLink == (int) section->size()) { | |
770 | 783 | setLinkIndex(iLink - 1); |
771 | link--; | |
784 | } | |
785 | --link; | |
772 | 786 | } |
773 | 787 | } |
774 | 788 | } |
... | ... | |
783 | 797 | #endif |
784 | 798 | #endif |
785 | 799 | |
786 | static bool compare_links(Link *a, Link *b) | |
800 | static bool compare_links(unique_ptr<Link> const& a, unique_ptr<Link> const& b) | |
787 | 801 | { |
788 | LinkApp *app1 = dynamic_cast<LinkApp *>(a); | |
789 | LinkApp *app2 = dynamic_cast<LinkApp *>(b); | |
802 | LinkApp *app1 = dynamic_cast<LinkApp *>(a.get()); | |
803 | LinkApp *app2 = dynamic_cast<LinkApp *>(b.get()); | |
790 | 804 | bool app1_is_opk = app1 && app1->isOpk(), |
791 | 805 | app2_is_opk = app2 && app2->isOpk(); |
792 | 806 | |
793 | if (app1_is_opk && !app2_is_opk) | |
794 | return false; | |
795 | if (app2_is_opk && !app1_is_opk) | |
796 | return true; | |
807 | if (app1_is_opk && !app2_is_opk) { | |
808 | return false; | |
809 | } | |
810 | if (app2_is_opk && !app1_is_opk) { | |
811 | return true; | |
812 | } | |
797 | 813 | return a->getTitle().compare(b->getTitle()) < 0; |
798 | 814 | } |
799 | 815 | |
... | ... | |
825 | 841 | } |
826 | 842 | |
827 | 843 | void Menu::readLinksOfSection( |
828 | vector<Link*>& links, string const& path, bool deletable) | |
844 | vector<unique_ptr<Link>>& links, string const& path, bool deletable) | |
829 | 845 | { |
830 | 846 | DIR *dirp = opendir(path.c_str()); |
831 | 847 | if (!dirp) return; |
... | ... | |
839 | 855 | link->setSize( |
840 | 856 | gmenu2x.skinConfInt["linkWidth"], |
841 | 857 | gmenu2x.skinConfInt["linkHeight"]); |
842 | links.push_back(link); | |
858 | links.emplace_back(link); | |
843 | 859 | } else { |
844 | 860 | delete link; |
845 | 861 | } |
src/menu.h | ||
---|---|---|
60 | 60 | int iSection, iLink; |
61 | 61 | uint iFirstDispRow; |
62 | 62 | std::vector<std::string> sections; |
63 | std::vector<std::vector<Link*>> links; | |
63 | std::vector<std::vector<std::unique_ptr<Link>>> links; | |
64 | 64 | |
65 | 65 | uint linkColumns, linkRows; |
66 | 66 | |
... | ... | |
72 | 72 | */ |
73 | 73 | void calcSectionRange(int &leftSection, int &rightSection); |
74 | 74 | |
75 | std::vector<Link*> *sectionLinks(int i = -1); | |
75 | std::vector<std::unique_ptr<Link>> *sectionLinks(int i = -1); | |
76 | 76 | |
77 | 77 | void readLinks(); |
78 | 78 | void freeLinks(); |
... | ... | |
89 | 89 | #endif |
90 | 90 | |
91 | 91 | // Load all the links on the given section directory. |
92 | void readLinksOfSection(std::vector<Link*>& links, | |
92 | void readLinksOfSection(std::vector<std::unique_ptr<Link>>& links, | |
93 | 93 | std::string const& path, bool deletable); |
94 | 94 | |
95 | 95 | /** |
Branches:
install_locations
master
opkrun
packages