00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <config.h>
00024 #include <locale.h>
00025 #include <iostream>
00026 #include <getopt.h>
00027 #ifdef MAEMO
00028 #include <locale.h>
00029 #endif
00030 #ifndef WIN32
00031 #include <libintl.h>
00032 #endif
00033 #ifdef MAEMO
00034 #include <syslog.h>
00035 #endif
00036 #include "kitlistgui.hpp"
00037 #include "kitlistpgsqldao.hpp"
00038 #include "xmldao.hpp"
00039
00068 using namespace std;
00069
00071 static int verbose_flag = 0;
00072
00074 static int html_flag = 0;
00075
00083 class KitList {
00084 protected:
00085 KitListDao* m_dao;
00086 public :
00087 KitList(const string dbname, const string user, const string port, bool verbose = false);
00088 ~KitList();
00089 KitListDao* get_dao() { return m_dao; }
00090 void add_item(const string name);
00091 void add_item(const string name, long cat_id);
00092 void append_items_to_category(long from_cat_id, long to_cat_id, item_choice choice);
00093 void associate_item_with_category(long id, long cat_id);
00094 void list_items_start(bool empty_list);
00095 void list_item(Item& item);
00096 void list_items_end(bool empty_list, size_t count);
00097 void list_items(Category& c);
00098 bool on_list_item(Item& item);
00099 void list_items(ItemContainer& items);
00100 void list_items(long cat_id, item_choice choice);
00101 void execute(ItemContainer& items, ItemFunctor& functor);
00102 void tick_items(Category& c);
00103 void tick_items(ItemContainer& items);
00104 void tick_items(long cat_id, item_choice choice);
00105 void list_categories();
00106 void new_category(const string name);
00107 void delete_category(long id);
00108 void delete_item(long id);
00109 void remove_item_from_category(long id, long cat_id);
00110 void set_item_flag(long id);
00111 void unset_item_flag(long id);
00112 void set_category_flag(long id);
00113 void unset_category_flag(long id);
00114 void set_all_flags();
00115 void unset_all_flags();
00116 };
00117
00118
00119 class TickItem : public ItemFunctor {
00120 ItemContainer& m_changed;
00121 public:
00122 TickItem(ItemContainer& changed) : ItemFunctor(), m_changed(changed) {}
00123 bool operator()(Item& item) {
00124 string s;
00125 cout << "Ticking item " << item.get_id() << " " << item.get_description() << endl;
00126 cout.width(6);
00127 cout << right << item.get_id()
00128 << '\t';
00129 cout.width(40);
00130 cout << left << item.get_description()
00131 << '\t' << " (" << (item.get_checked() ? "Yn" : "yN") << "q): ";
00132 getline(cin, s);
00133 bool checked = false;
00134 if (!s.empty()) {
00135 if (s == "y" || s == "Y") {
00136 checked = true;
00137 } else if (s == "n" || s == "N") {
00138 checked = false;
00139 } else if (s == "q" || s == "Q") {
00140 return true;
00141 }
00142 if (checked != item.get_checked()) {
00143 item.set_checked(checked);
00144 m_changed.push_back(&item);
00145 }
00146 }
00147 return false;
00148 }
00149
00150 };
00151
00152
00167 KitList::KitList(const string dbname, const string user, string port, bool verbose) {
00168 #ifdef XML_DAO
00169 m_dao = new XmlDao(verbose);
00170 #else
00171 m_dao = new KitListPgsqlDao(dbname, user, port, verbose);
00172 #endif
00173 }
00174
00175
00176 KitList::~KitList() {
00177 delete m_dao;
00178 }
00179
00180
00189 void KitList::add_item(const string name, long cat_id) {
00190 if (cat_id >= 0) {
00191 long id = m_dao->add_item(name, cat_id);
00192 cout << "Added item with id " << id << " to category " << cat_id << endl << endl;
00193 } else {
00194 long id = m_dao->add_item(name);
00195 cout << "Added item with id " << id << endl << endl;
00196 }
00197 }
00198
00199
00208 void KitList::append_items_to_category(long from_cat_id, long to_cat_id, item_choice choice) {
00209 m_dao->append_items_to_category(to_cat_id, from_cat_id, choice);
00210 }
00211
00212
00219 void KitList::associate_item_with_category(long id, long cat_id) {
00220 m_dao->associate_item_with_category(id, cat_id);
00221 cout << "Associated item " << id << " with category " << cat_id << endl << endl;
00222 }
00223
00224
00228 bool KitList::on_list_item(Item& item) {
00229 list_item(item);
00230 return false;
00231 }
00232
00233
00243 void KitList::list_items_start(bool empty_list) {
00244 if (html_flag)
00245 cout << "<html>" << endl
00246 << "<head>" << endl
00247 << "<title>Items</title>" << endl
00248 << "</head>" << endl
00249 << "<body>" << endl;
00250
00251 if (!empty_list) {
00252 if (html_flag) {
00253 cout << "<table cellpadding=\"3\" cellspacing=\"0\" border=\"1\">" << endl
00254 << "<tr><th>ID</th><th>Description</th></tr>" << endl;
00255 } else {
00256 cout.width(6);
00257 cout << right << "ID" << "\tDescription" << endl;
00258 cout << right << "======" << "\t===========" << endl;
00259 }
00260 }
00261 }
00262
00263
00274 void KitList::list_items_end(bool empty_list, size_t count) {
00275 if (!empty_list) {
00276 if (html_flag)
00277 cout << "</table>" << endl;
00278 }
00279
00280 if (html_flag) {
00281 cout << "<p>" << count << " items</p>" << endl
00282 << "</body>" << endl << "</html>" << endl;
00283 } else {
00284 cout << endl;
00285 cout.width(6);
00286 cout << count << " items" << endl << endl;
00287 }
00288 }
00289
00290
00297 void KitList::list_item(Item& item) {
00298 if (html_flag) {
00299 cout << "<tr><td>" << item.get_id() << "</td>"
00300 << "<td>" << item.get_description() << "</td></tr>" << endl;
00301 } else {
00302 cout.width(6);
00303 cout << item.get_id();
00304 cout << '\t' << item.get_description()
00305 << endl;
00306 }
00307 }
00308
00309
00313 void KitList::list_items(Category& c) {
00314 list_items_start(!c.has_items());
00315 c.foreach_item( sigc::mem_fun(*this, &KitList::on_list_item) );
00316 list_items_end(!c.has_items(), c.item_count());
00317 }
00318
00319
00323 void KitList::list_items(ItemContainer& items) {
00324 list_items_start(items.empty());
00325 for (ItemIter i = items.begin(); i != items.end(); ++i ) {
00326 list_item(**i);
00327 }
00328 list_items_end(items.empty(), items.size());
00329 }
00330
00331
00341 void KitList::list_items(long cat_id, item_choice choice = ALL_ITEMS) {
00342 if (cat_id >=0 ) {
00343 Category* cat = m_dao->get_category(cat_id, choice);
00344 list_items(*cat);
00345 delete cat;
00346 } else {
00347 ItemContainer* items = m_dao->get_all_items(choice);
00348 list_items(*items);
00349 for (ItemIter i = items->begin(); i != items->end(); ++i) {
00350 delete (*i);
00351 }
00352 delete items;
00353 }
00354 }
00355
00356
00361 void KitList::execute(ItemContainer& items, ItemFunctor& functor) {
00362 for (ItemIter i = items.begin(); i != items.end(); ++i) {
00363 if (functor(**i))
00364 break;
00365 }
00366 }
00367
00368
00372 void KitList::tick_items(ItemContainer& items) {
00373 ItemContainer changed;
00374 TickItem t(changed);
00375 execute(items, t);
00376 m_dao->update_item_checked_state(changed);
00377 }
00378
00379
00383 void KitList::tick_items(Category& c) {
00384 ItemContainer changed;
00385 TickItem t(changed);
00386 c.execute(t);
00387 m_dao->update_item_checked_state(changed);
00388 }
00389
00390
00399 void KitList::tick_items(long cat_id, item_choice choice = ALL_ITEMS) {
00400 if (cat_id >=0 ) {
00401 Category* cat = m_dao->get_category(cat_id, choice);
00402 tick_items(*cat);
00403 delete cat;
00404 } else {
00405 ItemContainer* items = m_dao->get_all_items(choice);
00406 tick_items(*items);
00407 for (ItemIter i = items->begin(); i != items->end(); ++i) {
00408 delete (*i);
00409 }
00410 delete items;
00411 }
00412 }
00413
00414
00418 void KitList::delete_item(long id) {
00419 m_dao->delete_item(id);
00420 cout << "Deleted item with id " << id << endl << endl;
00421 }
00422
00423
00430 void KitList::remove_item_from_category(long id, long cat_id) {
00431 m_dao->remove_item_from_category(id, cat_id);
00432 cout << "Removed item " << id << " from category " << cat_id << endl << endl;
00433 }
00434
00435
00440 void KitList::delete_category(long id) {
00441 m_dao->delete_category(id);
00442 cout << "Deleted category with id " << id << endl << endl;
00443 }
00444
00445
00452 void KitList::list_categories() {
00453 CategoryContainer c = m_dao->get_categories();
00454
00455 if (html_flag)
00456 cout << "<html>" << endl
00457 << "<head>" << endl
00458 << "<title>Categories</title>" << endl
00459 << "</head>" << endl
00460 << "<body>" << endl;
00461
00462 if (!c.empty()) {
00463 if (html_flag) {
00464 cout << "<table cellpadding=\"3\" cellspacing=\"0\" border=\"1\">" << endl
00465 << "<tr><th>ID</th><th>Description</th></tr>" << endl;
00466 } else {
00467 cout.width(6);
00468 cout << right << "ID" << "\tDescription" << endl;
00469 cout << right << "======" << "\t===========" << endl;
00470 }
00471 for (CategoryIter i = c.begin(); i != c.end(); ++i) {
00472 if (html_flag) {
00473 cout << "<tr><td>" << (*i)->get_id() << "</td>"
00474 << "<td>" << (*i)->get_name() << "</td></tr>" << endl;
00475 } else {
00476 cout.width(6);
00477 cout << (*i)->get_id()
00478 << "\t" << (*i)->get_name() << endl;
00479 }
00480 delete (*i);
00481 }
00482
00483 if (html_flag)
00484 cout << "</table>" << endl;
00485
00486 }
00487 if (html_flag) {
00488 cout << "<p>" << c.size() << " categories</p>" << endl
00489 << "</body>" << endl << "</html>" << endl;
00490 } else {
00491 cout << endl;
00492 cout.width(6);
00493 cout << c.size() << " categories" << endl << endl;
00494 }
00495 }
00496
00497
00501 void KitList::new_category(const string name) {
00502 long id = m_dao->new_category(name);
00503 cout << "Added category id " << id << " named \"" << name << '"' << endl << endl;
00504 }
00505
00506
00510 void KitList::set_item_flag(long id) {
00511 m_dao->set_item_flag(id);
00512 cout << "Checked item with id " << id << endl << endl;
00513 }
00514
00515
00519 void KitList::unset_item_flag(long id) {
00520 m_dao->unset_item_flag(id);
00521 cout << "Unchecked items with id " << id << endl << endl;
00522 }
00523
00524
00528 void KitList::set_category_flag(long id) {
00529 m_dao->set_category_flag(id);
00530 cout << "Checked items with category id " << id << endl << endl;
00531 }
00532
00533
00537 void KitList::unset_category_flag(long id) {
00538 m_dao->unset_category_flag(id);
00539 cout << "Unchecked items with category id " << id << endl << endl;
00540 }
00541
00542
00546 void KitList::set_all_flags() {
00547 m_dao->set_all_flags();
00548 cout << "Checked all items" << endl << endl;
00549 }
00550
00551
00555 void KitList::unset_all_flags() {
00556 m_dao->unset_all_flags();
00557 cout << "Unchecked all items" << endl << endl;
00558 }
00559
00560
00564 int main(int argc, char **argv) {
00565 setlocale(LC_CTYPE, "");
00566
00567 #ifndef WIN32
00568
00569 bindtextdomain(GETTEXT_PACKAGE, PROGRAMNAME_LOCALEDIR);
00570 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
00571 textdomain(GETTEXT_PACKAGE);
00572 #endif //WIN32
00573 int c;
00574 string port;
00575 string item_desc;
00576 string cat_desc;
00577 int option_index = 0;
00578 int invalid_opt = false;
00579 long cat_n = -1;
00580 long dest_cat_n = -1;
00581 long item_n = -1;;
00582 int force_flag = 0;
00583 item_choice checked_items_flag = ALL_ITEMS;
00584 enum actions {NOP,
00585 SHOW_GUI,
00586 ADD_ITEM,
00587 COPY_ITEMS,
00588 ASSOCIATE_ITEM,
00589 LIST,
00590 LIST_CHECKED,
00591 LIST_UNCHECKED,
00592 TICK_CHECKED,
00593 TICK_UNCHECKED,
00594 NEW_CATEGORY,
00595 LIST_CATEGORIES,
00596 DELETE,
00597 SET,
00598 CLEAR,
00599 SET_ALL,
00600 CLEAR_ALL};
00601 enum actions action = NOP;
00602
00603 while (1) {
00604 static struct option long_options[] = {
00605 #ifndef XML_DAO
00606 {"port", required_argument, 0, 'p'},
00607 {"html", no_argument, &html_flag, 1},
00608 {"no-html", no_argument, &html_flag, 0},
00609 {"force", no_argument, &force_flag, 1},
00610 {"add", required_argument, 0, 'a'},
00611 {"add-to-category", no_argument, 0, 'A'},
00612 {"category", required_argument, 0, 'c'},
00613 {"copy-to-category", required_argument, 0, 'C'},
00614 {"only-unchecked", no_argument, 0, 'k'},
00615 {"only-checked", no_argument, 0, 'K'},
00616 {"item", required_argument, 0, 'i'},
00617 {"list", no_argument, 0, 'l'},
00618 {"list-checked", no_argument, 0, 'X'},
00619 {"list-unchecked", no_argument, 0, 'U'},
00620 {"list-categories", no_argument, 0, 'q'},
00621 {"tick-unchecked", no_argument, 0, 't'},
00622 {"tick-checked", no_argument, 0, 'T'},
00623 {"new-category", required_argument, 0, 'n'},
00624 {"delete", no_argument, 0, 'd'},
00625 {"set", no_argument, 0, 'x'},
00626 {"clear", no_argument, 0, 'u'},
00627 {"set-all", no_argument, 0, 's'},
00628 {"clear-all", no_argument, 0, 'z'},
00629 {"interactive", no_argument, 0, 'g'},
00630 #endif
00631 {"verbose", no_argument, &verbose_flag, 1},
00632 {"brief", no_argument, &verbose_flag, 0},
00633 {"help", no_argument, 0, 'h'},
00634 {"version", no_argument, 0, 'v'},
00635 {0, 0, 0, 0}
00636 };
00637 #ifndef XML_DAO
00638 c = getopt_long(argc, argv, "hvVHp:fa:Ac:C:i:lXUqtTn:dxuszkKg",
00639 long_options, &option_index);
00640 #else
00641 c = getopt_long(argc, argv, "hvV",
00642 long_options, &option_index);
00643 #endif
00644 if (c == -1)
00645 break;
00646
00647 switch (c) {
00648 case 0:
00649 break;
00650
00651 case 'p':
00652 port = optarg;
00653 break;
00654
00655 case 'h':
00656 cout << "Usage:" << endl
00657 #ifndef XML_DAO
00658 << " " << argv[0] << " [OPTIONS] [DBNAME [USERNAME]]" << endl << endl
00659 #else
00660 << " " << argv[0] << " [FILENAME]" << endl << endl
00661 #endif
00662 << "Options:" << endl
00663 << " -h, --help\t\t\t\tshow this help, then exit" << endl
00664 << " -v, --version\t\t\t\tshow version information, then exit" << endl
00665 << " -V, --verbose\t\t\t\tverbose output" << endl
00666 #ifndef XML_DAO
00667 << " -g, --interactive\t\t\tDisplay interactive GUI" << endl
00668 << " -p, --port=PORT\t\tspecify the port to connect to, default 5432" << endl
00669 << " -a, --add=NAME\t\t\tcreate item named NAME," << endl
00670 << " \t\t\tif -c specified, associates item with that category" << endl
00671 << " -A, --add-to-category\t\tadd existing item to category" << endl
00672 << " \t\t\t\t\tboth -i and -c must be specified" << endl
00673 << " -l, --list\t\t\t\tlist all items, limit to category, if -c specified" << endl
00674 << " -X, --list-checked\t\tsame as -l, except only checked items" << endl
00675 << " -U, --list-unchecked\t\tsame as -l, except only unchecked items" << endl
00676 << " -T, --tick-checked\t\tinteratively choose to tick/untick checked items" << endl
00677 << " -t, --tick-unchecked\t\tinteratively choose to tick/untick unchecked items" << endl
00678 << " -q, --list-categories\t\tlist categories" << endl
00679 << " -n, --new-category=CATEGORY\tcreate category named CATEGORY" << endl
00680 << " -c, --category=NUMBER\t\tspecify category number for action" << endl
00681 << " -C, --copy-to-category=NUMBER\t\tcopy all or specific category to" << endl
00682 << " \t\t\t\t\tcategory NUMBER. Specify source category with -c" << endl
00683 << " \t\t\t\t\tor omit to copy all items" << endl
00684 << " -k, --only-unchecked\t\tWhen using -C, operate on unchecked items only" << endl
00685 << " -K, --only-checked\t\tWhen using -C, operate on checked items only" << endl
00686 << " -i, --item=NUMBER\t\t\tspecify item number for action" << endl
00687 << " -d, --delete\t\t\t\tdelete category or item specified by -c or -i, if" << endl
00688 << " \t\t\t\t\tboth -i and -c are specifed, simply removes the " << endl
00689 << " \t\t\t\t\tassociation between them" << endl
00690 << " -x, --set\t\t\t\t\tset flag for item specified by -i" << endl
00691 << " -u, --clear\t\t\t\tclear flag for item specified by -i" << endl
00692 << " -s, --set-all\t\t\t\tsets all flags" << endl
00693 << " -z, --clear-all\t\t\tclears all flags" << endl
00694 << " -H, --html\t\t\t\thtml formatted output" << endl
00695 #endif
00696 ;
00697 return 0;
00698
00699 case 'v':
00700 cout << "kitlist " << VERSION << endl;
00701 return 0;
00702
00703 case 'V':
00704 verbose_flag = 1;
00705 break;
00706
00707 case 'H':
00708 html_flag = 1;
00709 break;
00710
00711 case '?':
00712 invalid_opt = true;
00713 break;
00714
00715 case 'i':
00716 item_n = strtol(optarg, NULL, 0);
00717 break;
00718 case 'c':
00719 cat_n = strtol(optarg, NULL, 0);
00720 break;
00721 case 'C':
00722 action = COPY_ITEMS;
00723 dest_cat_n = strtol(optarg, NULL, 0);
00724 break;
00725 case 'a':
00726 action = ADD_ITEM;
00727 item_desc = optarg;
00728 break;
00729 case 'A':
00730 action = ASSOCIATE_ITEM;
00731 break;
00732 case 'l':
00733 action = LIST;
00734 break;
00735 case 'X':
00736 action = LIST_CHECKED;
00737 break;
00738 case 'U':
00739 action = LIST_UNCHECKED;
00740 break;
00741 case 'T':
00742 action = TICK_CHECKED;
00743 break;
00744 case 't':
00745 action = TICK_UNCHECKED;
00746 break;
00747 case 'q':
00748 action = LIST_CATEGORIES;
00749 break;
00750
00751 case 'n':
00752 action = NEW_CATEGORY;
00753 cat_desc = optarg;
00754 break;
00755
00756 case 'd':
00757 action = DELETE;
00758 break;
00759
00760 case 'x':
00761 action = SET;
00762 break;
00763
00764 case 'u':
00765 action = CLEAR;
00766 break;
00767
00768 case 's':
00769 action = SET_ALL;
00770 break;
00771
00772 case 'z':
00773 action = CLEAR_ALL;
00774 break;
00775
00776 case 'f':
00777 force_flag = 1;
00778 break;
00779
00780 case 'k':
00781 checked_items_flag = UNCHECKED_ITEMS;
00782 break;
00783
00784 case 'K':
00785 checked_items_flag = CHECKED_ITEMS;
00786 break;
00787
00788 case 'g':
00789 action = SHOW_GUI;
00790 break;
00791
00792 default:
00793 abort();
00794 }
00795 }
00796 if (invalid_opt)
00797 return 1;
00798 int index;
00799 index = optind;
00800 string dbname = (index < argc) ? argv[index++] : "";
00801 string user = (index < argc) ? argv[index++] : "";
00802
00803 KitList kit(dbname, user, port, verbose_flag);
00804
00805 #ifndef XML_DAO
00806
00807 action = (argc == 1) ? SHOW_GUI : action;
00808 #else
00809
00810 action = SHOW_GUI;
00811 #endif
00812
00813 switch (action) {
00814 case ADD_ITEM:
00815 kit.add_item(item_desc, cat_n);
00816 break;
00817 case COPY_ITEMS:
00818 if (cat_n >= 0 || force_flag) {
00819 kit.append_items_to_category(cat_n, dest_cat_n, checked_items_flag);
00820 } else {
00821 cerr << "Specify -f (--force) to copy all items to a category" << endl << endl;
00822 }
00823 break;
00824 case ASSOCIATE_ITEM:
00825 if (item_n >= 0 && cat_n >=0) {
00826 kit.associate_item_with_category(item_n, cat_n);
00827 } else {
00828 cerr << "You must specify the item and category using -i and -c" << endl << endl;
00829 }
00830 break;
00831 case LIST:
00832 kit.list_items(cat_n);
00833 break;
00834 case LIST_CHECKED:
00835 kit.list_items(cat_n, CHECKED_ITEMS);
00836 break;
00837 case LIST_UNCHECKED:
00838 kit.list_items(cat_n, UNCHECKED_ITEMS);
00839 break;
00840 case TICK_CHECKED:
00841 kit.tick_items(cat_n, CHECKED_ITEMS);
00842 break;
00843 case TICK_UNCHECKED:
00844 kit.tick_items(cat_n, UNCHECKED_ITEMS);
00845 break;
00846 case LIST_CATEGORIES:
00847 kit.list_categories();
00848 break;
00849 case NEW_CATEGORY:
00850 kit.new_category(cat_desc);
00851 break;
00852 case DELETE:
00853 if (cat_n >= 0 && item_n >=0) {
00854 kit.remove_item_from_category(item_n, cat_n);
00855 } else if (item_n >=0) {
00856 kit.delete_item(item_n);
00857 } else {
00858 if (force_flag) {
00859 kit.delete_category(cat_n);
00860 } else {
00861 cerr << "Specify -f (--force) to delete a category" << endl << endl;
00862 return 1;
00863 }
00864 }
00865 break;
00866
00867 case SET:
00868 if (item_n >=0) {
00869 kit.set_item_flag(item_n);
00870 } else {
00871 cerr << "Specify an item set using -i or --item" << endl << endl;
00872 return 1;
00873 }
00874 break;
00875 case CLEAR:
00876 if (item_n >=0) {
00877 kit.unset_item_flag(item_n);
00878 } else {
00879 cerr << "Specify an item to clear using -i or --item" << endl << endl;
00880 return 1;
00881 }
00882 break;
00883 case SET_ALL:
00884 if (cat_n >=1) {
00885 kit.set_category_flag(cat_n);
00886 } else {
00887 if (force_flag) {
00888 kit.set_all_flags();
00889 } else {
00890 cerr << "Specify -f (--force) to set all flags" << endl << endl;
00891 }
00892 }
00893 break;
00894 case CLEAR_ALL:
00895 if (cat_n >=1) {
00896 kit.unset_category_flag(cat_n);
00897 } else {
00898 if (force_flag) {
00899 kit.unset_all_flags();
00900 } else {
00901 cerr << "Specify -f (--force) to clear all flags" << endl << endl;
00902 }
00903 }
00904 break;
00905 case SHOW_GUI:
00906 Service service(*kit.get_dao());
00907 KitListGui gui(argc, argv, service);
00908 #ifdef XML_DAO
00909
00910
00911
00912 if (dbname.length() > 0)
00913 gui.open_file(dbname);
00914 #endif
00915 gui.run();
00916 break;
00917 }
00918
00919 }