25#include <final/final.h>
31using namespace finalcut;
38 setText(
"Categories");
43 const auto w = getWidth();
44 const auto h = getHeight();
45 category_list->setGeometry(FPoint{2, 3}, FSize{w - 2, h - 3});
46 FDialog::adjustSize();
51 const auto w = getDesktopWidth() / 2 - 15;
52 const auto h = getDesktopHeight() - 4;
56 setGeometry(FPoint{2, 2}, FSize{w, h - 1});
57 setMinimumSize(FSize{20, 12});
58 FDialog::initLayout();
70 const auto cats =
base_app->get_categories();
71 for (
const auto& cat : cats) {
72 FListBoxItem lbi{cat->name, cat->get_id()};
93 auto parent = getParent();
94 assert(parent->getClassName() ==
"KitListWindow");
95 if (parent->getClassName() ==
"KitListWindow")
103 const auto category_id = i.getData<int32_t>();
104 auto parent = getParentWidget();
107 auto list = klw->get_item_dialog_for_category_id(category_id);
126 const auto category_id = i.getData<int32_t>();
140 setText(
"All Items");
145 setText(category->get_name());
158 auto items =
base_app->filter_items_for_current_selected_category();
161 for (
const auto& i : items) {
162 FStringList str_list{};
163 const FString name{i->name};
164 str_list.push_back(name);
166 auto item =
static_cast<finalcut::FListViewItem*
>(*iter);
167 item->setData(i->get_id());
168 item->setChecked(i->is_checked());
169 item->setCheckable(
true);
180 const int32_t item_id = p->getData<int32_t>();
181 shared_ptr<Item> item =
182 base_app->set_item_checked(item_id, p->isChecked());
185 auto parent = getParentWidget();
187 static_cast<KitListWindow*
>(parent)->refresh_item_dialogs(item);
196 const auto id = item->get_id();
197 bool changed =
false;
198 for (
auto i : items) {
199 if (i->getData<int32_t>() ==
id && i->isChecked() != item->is_checked()) {
201 i->setChecked(item->is_checked());
211 finalcut::FDialog::onFocusIn(ev);
212 auto parent = getParent();
213 assert(parent->getClassName() ==
"KitListWindow");
214 if (parent->getClassName() ==
"KitListWindow")
223 const auto item_id = p->getData<int32_t>();
224 auto item =
base_app->get_item(item_id);
228 FMessageBox mb{
"Delete Item",
229 "Are you sure you want to delete the \"" + item->get_name() +
"\" item?",
230 FMessageBox::ButtonType::Cancel,
231 FMessageBox::ButtonType::Yes,
232 FMessageBox::ButtonType::No,
234 auto result = mb.exec();
235 if (result != FMessageBox::ButtonType::Yes)
246 const auto item_id = p->getData<int32_t>();
247 auto item =
base_app->get_item(item_id);
251 FMessageBox mb{
"Remove Item",
252 "Are you sure you want to remove the \"" + item->get_name() +
"\" item?",
253 FMessageBox::ButtonType::Cancel,
254 FMessageBox::ButtonType::Yes,
255 FMessageBox::ButtonType::No,
257 auto result = mb.exec();
258 if (result != FMessageBox::ButtonType::Yes)
269 auto h = getHeight();
271 FDialog::adjustSize();
276 const auto left = getDesktopWidth() / 2 - 10;
277 const auto w = getDesktopWidth() / 2 + 8;
278 const auto h = getDesktopHeight() - 4;
281 setGeometry(FPoint{
static_cast<int>(left), 2}, FSize{w, h - 1});
282 setMinimumSize(FSize{20, 12});
283 FDialog::initLayout();
285 assert(focus_result);
295 if (this->category_id >=0 ) {
321 const auto w = getDesktopWidth();
322 setGeometry(finalcut::FPoint{4, 2}, FSize{w - 6 , 11});
323 setMinimumSize(finalcut::FSize{30, 10});
324 btn_cancel.setGeometry(FPoint{17, 5}, FSize{8, 1});
325 btn_ok.setGeometry(FPoint{33, 5}, FSize{8, 1});
326 FDialog::initLayout();
331 const auto dw = getWidth() - 22;
332 input_name.setGeometry(FPoint{17, 2}, FSize{dw, 1});
333 FDialog::adjustSize();
343 if (this->item_id >=0 ) {
370 const auto w = getDesktopWidth();
371 setGeometry(finalcut::FPoint{4, 2}, FSize{w - 6 , 11});
372 setMinimumSize(finalcut::FSize{30, 12});
373 checkbox.setGeometry(FPoint{17, 5}, FSize{22, 1});
374 btn_cancel.setGeometry(FPoint{17, 7}, FSize{8, 1});
375 btn_ok.setGeometry(FPoint{33, 7}, FSize{8, 1});
376 FDialog::initLayout();
381 const auto dw = getWidth() - 22;
382 input_name.setGeometry(FPoint{17, 2}, FSize{dw, 1});
383 FDialog::adjustSize();
390 setText(
"Select Categories");
396 done(ResultCode::Accept);
403 done(ResultCode::Reject);
410 const auto w = getDesktopWidth();
411 const auto vertical_middle = w / 2;
412 const auto h = getDesktopHeight();
415 category_list->setStatusbarMessage(
"Use spacebar to select categories");
417 setGeometry(FPoint{
static_cast<int>(vertical_middle) - 15, 4},
419 setMinimumSize(FSize{28, 12});
420 FDialog::initLayout();
422 assert(focus_result);
427 const auto w = getWidth();
428 const auto h = getHeight();
429 const auto vertical_middle = w / 2;
430 category_list->setGeometry(FPoint{2, 3}, FSize{w - 2, h - 5});
431 btn_cancel.setGeometry(FPoint{
static_cast<int>(vertical_middle) - 10,
432 static_cast<int>(h) - 4}, FSize{8, 1});
433 btn_ok.setGeometry(FPoint{
static_cast<int>(vertical_middle) + 4,
434 static_cast<int>(h) - 4}, FSize{8, 1});
435 FDialog::adjustSize();
440 const auto cats =
base_app->get_categories();
441 for (
const auto& cat : cats) {
442 FListBoxItem lbi{cat->name, cat->get_id()};
450 vector<int32_t> retval{};
452 for (
const auto& i : list_box_items) {
453 if (i.isSelected()) {
454 const auto category_id = i.getData<int32_t>();
455 retval.push_back(category_id);
464 FApplication app{argc, argv};
469 cerr <<
"File not found: \"" <<
filename <<
"\" - " << e.
what() <<
'\n';
470 app.exit(EXIT_FAILURE);
472 cerr <<
"Error parsing file: \"" <<
filename <<
"\" - " << e.
what() <<
'\n';
473 app.exit(EXIT_FAILURE);
483 FWidget::setMainWidget(&main_window);
492 main_menu.file_menu.setStatusbarMessage(
"File commands");
506 d->populate_category_list();
520 for (
const auto& child : getChildren()) {
521 const auto class_name = child->getClassName();
522 if (class_name ==
"ItemListDialog") {
532 for (
const auto& child : getChildren()) {
533 const auto class_name = child->getClassName();
534 if (class_name ==
"ItemListDialog") {
544 for (
const auto& child : getChildren()) {
545 const auto class_name = child->getClassName();
546 if (class_name ==
"ItemListDialog") {
556 main_menu.file_new.addAccelerator(FKey::Ctrl_n);
557 main_menu.file_new.setStatusbarMessage(
"Create a new kitlist");
559 main_menu.file_open.addAccelerator(FKey::Ctrl_o);
560 main_menu.file_open.setStatusbarMessage(
"Open another kitlist");
562 main_menu.file_save.addAccelerator(FKey::Ctrl_s);
563 main_menu.file_save.setStatusbarMessage(
"Saves the changes");
565 main_menu.file_save.setStatusbarMessage(
"Saves the changes to a new file");
569 main_menu.file_quit.addAccelerator(FKey::Ctrl_q);
570 main_menu.file_quit.setStatusbarMessage(
"Quit");
599 &FApplication::cb_exitApp,
605 main_menu.new_item.setStatusbarMessage(
"Create a new item");
606 main_menu.edit_item.setStatusbarMessage(
"Edit the selected item");
607 main_menu.new_category.setStatusbarMessage(
"Create a new category");
608 main_menu.edit_category.setStatusbarMessage(
"Rename the selected category");
612 main_menu.delete_item.setStatusbarMessage(
"Delete the currently selected item");
613 main_menu.remove_item.setStatusbarMessage(
"Remove the currently selected item from the category");
614 main_menu.delete_category.setStatusbarMessage(
"Delete the currently selected category");
618 main_menu.remove_checked_items.setStatusbarMessage(
"Remove the checked items from the category");
619 main_menu.delete_checked_items.setStatusbarMessage(
"Permanently delete the checked items");
623 main_menu.check_items.setStatusbarMessage(
"Check the items");
624 main_menu.uncheck_items.setStatusbarMessage(
"Uncheck the items");
625 main_menu.toggle_items.setStatusbarMessage(
"Toggle the checked state of the items");
629 main_menu.copy_item.setStatusbarMessage(
"Copy the selected item to categories");
630 main_menu.copy_checked_items.setStatusbarMessage(
"Copy the checked items to other categories");
674 main_menu.remove_checked_items.addCallback(
680 main_menu.delete_checked_items.addCallback(
710 main_menu.copy_checked_items.addCallback(
719 main_menu.view_category_list.setStatusbarMessage(
"View list of categories…");
720 main_menu.view_category_list.addAccelerator(FKey::Ctrl_e);
722 main_menu.view_all_items_list.addAccelerator(FKey::Ctrl_b);
723 main_menu.view_all_items_list.setStatusbarMessage(
"View list of all items");
727 main_menu.view_checked_unchecked.setStatusbarMessage(
"View both checked and unchecked items");
728 main_menu.view_checked.setStatusbarMessage(
"View only checked items");
729 main_menu.view_unchecked.setStatusbarMessage(
"View only unchecked items");
732 main_menu.view_category_list.addCallback(
738 main_menu.view_all_items_list.addCallback(
744 main_menu.view_checked_unchecked.addCallback(
766 window.setStatusbarMessage (
"List of active dialogs");
771 const int pw = getDesktopWidth();
772 const int ph = getDesktopHeight();
773 setX(1 + (pw -
int(getWidth())) / 2,
false);
774 setY(1 + (ph -
int(getHeight())) / 4,
false);
777 FWidget::adjustSize();
822 FMessageBox mb{
"Unsaved Changes",
823 "Changes not saved. Are you sure you want to abandon your changes?",
824 FMessageBox::ButtonType::Cancel,
825 FMessageBox::ButtonType::Yes,
826 FMessageBox::ButtonType::No,
828 auto result = mb.exec();
829 if (result != FMessageBox::ButtonType::Yes)
849 FMessageBox mb{
"Unsaved Changes",
850 "Changes not saved. Are you sure you want to abandon your changes?",
851 FMessageBox::ButtonType::Cancel,
852 FMessageBox::ButtonType::Yes,
853 FMessageBox::ButtonType::No,
855 auto result = mb.exec();
856 if (result != FMessageBox::ButtonType::Yes)
859 auto f = FFileDialog::fileOpenChooser(
this,
".",
"*.kit");
865 FMessageBox mb{
"Error",
866 "The file was not found",
867 FMessageBox::ButtonType::Ok,
868 FMessageBox::ButtonType::Reject,
869 FMessageBox::ButtonType::Reject,
874 FMessageBox mb{
"Error",
875 "Failed to parse file",
876 FMessageBox::ButtonType::Ok,
877 FMessageBox::ButtonType::Reject,
878 FMessageBox::ButtonType::Reject,
898 if (
base_app->get_filename().empty())
911 auto f = fileChooser(
this,
".",
"*.kit", FFileDialog::DialogType::Save);
918 status_bar.setMessage(
"Failed to save file \"" + f +
'"');
932 const auto item_name = d.
get_name();
933 if (item_name.isEmpty())
942 FApplication::getApplicationObject()->queueEvent(getMainWidget(), &user_event);
947 auto aw = getActiveWindow();
948 if (aw->getClassName() !=
"ItemListDialog")
952 const auto p = ild->item_list_view.getCurrentItem();
953 const auto item_id = p->getData<int32_t>();
954 auto item =
base_app->get_item(item_id);
966 const auto item_name = d.
get_name();
967 if (item_name.isEmpty())
970 base_app->set_item_name(item_id, item_name.toString());
983 const auto category_name = d.
get_name();
984 if (category_name.isEmpty())
987 base_app->new_category(category_name.toString());
993 FApplication::getApplicationObject()->queueEvent(getMainWidget(), &user_event);
1002 shared_ptr<Category> category = cd->get_current_category();
1013 const auto category_name = d.
get_name();
1014 if (category_name.isEmpty())
1019 list->setText(category_name);
1020 base_app->set_category_name(category->get_id(), category_name.toString());
1027 auto aw = getActiveWindow();
1028 if (aw->getClassName() !=
"ItemListDialog")
1031 if (d->delete_current_item())
1037 auto aw = getActiveWindow();
1038 if (aw->getClassName() !=
"ItemListDialog")
1041 d->remove_current_item();
1048 shared_ptr<Category> category =
nullptr;
1049 if (cd && (category = cd->get_current_category())) {
1052 base_app->delete_category(category->get_id());
1055 auto aw = getActiveWindow();
1057 const auto class_name = aw->getClassName();
1058 if (class_name ==
"ItemListDialog") {
1059 const auto cid =
static_cast<ItemListDialog*
>(aw)->get_category_id();
1061 category =
base_app->get_category(cid);
1076 auto aw = getActiveWindow();
1077 if (aw->getClassName() !=
"ItemListDialog")
1080 base_app->select_category(d->get_category_id());
1081 base_app->remove_all_current_checked_items();
1087 auto aw = getActiveWindow();
1088 if (aw->getClassName() !=
"ItemListDialog")
1091 base_app->select_category(d->get_category_id());
1092 base_app->delete_all_current_checked_items();
1098 auto aw = getActiveWindow();
1099 if (aw->getClassName() !=
"ItemListDialog")
1102 base_app->select_category(d->get_category_id());
1109 auto aw = getActiveWindow();
1110 if (aw->getClassName() !=
"ItemListDialog")
1113 base_app->select_category(d->get_category_id());
1120 auto aw = getActiveWindow();
1121 if (aw->getClassName() !=
"ItemListDialog")
1124 base_app->select_category(d->get_category_id());
1131 auto aw = getActiveWindow();
1132 if (aw->getClassName() !=
"ItemListDialog")
1135 auto cid = ild->get_category_id();
1138 const auto p = ild->item_list_view.getCurrentItem();
1139 const auto item_id = p->getData<int32_t>();
1143 auto result = scd.exec();
1144 if (result != FDialog::ResultCode::Accept)
1146 auto cids = scd.get_selected_category_ids();
1149 base_app->copy_item_to_categories(item_id, cids);
1155 auto aw = getActiveWindow();
1156 if (aw->getClassName() !=
"ItemListDialog")
1159 auto cid = ild->get_category_id();
1163 auto result = scd.exec();
1164 if (result != FDialog::ResultCode::Accept)
1169 base_app->copy_checked_items_to_categories(cids);
1179 FMessageBox mb{
"Unsaved Changes",
1180 "Changes not saved. Are you sure you want to quit?",
1181 FMessageBox::ButtonType::Cancel,
1182 FMessageBox::ButtonType::Yes,
1183 FMessageBox::ButtonType::No,
1185 auto result = mb.exec();
1186 if (result == FMessageBox::ButtonType::Yes)
1195 if (category_dialog) {
1234 if (
window->isMinimized())
1235 window->minimizeWindow();
1236 auto focus = getFocusWidget();
1237 FAccelEvent ev (Event::Accelerator, focus);
1238 FApplication::sendEvent (
window, &ev);
1242 FMessageBox mb{
"Delete Category",
1243 "Are you sure you want to delete the \"" + category->get_name() +
"\" category?",
1244 FMessageBox::ButtonType::Cancel,
1245 FMessageBox::ButtonType::Yes,
1246 FMessageBox::ButtonType::No,
1248 auto result = mb.exec();
1249 return (result == FMessageBox::ButtonType::Yes);
1254 for (
const auto& child : getChildren())
1255 if (child->getClassName() ==
"CategoryListDialog")
1262 for (
const auto& child : getChildren()) {
1263 const auto class_name = child->getClassName();
1264 if (class_name ==
"ItemListDialog") {
1278 main_menu.view_checked_unchecked.setChecked();
1280 main_menu.view_unchecked.unsetChecked();
1283 main_menu.view_checked_unchecked.unsetChecked();
1285 main_menu.view_unchecked.unsetChecked();
1288 main_menu.view_checked_unchecked.unsetChecked();
1298 const bool dirty =
base_app->is_dirty();
1299 bool all_item_list_on_top =
false;
1300 bool have_visible_items =
false;
1301 bool have_visible_categories =
false;
1302 bool item_list_on_top =
false;
1303 bool category_list_on_top =
false;
1304 auto aw = getActiveWindow();
1306 item_list_on_top = aw->getClassName() ==
"ItemListDialog";
1307 if (item_list_on_top) {
1310 have_visible_items = ild->is_items();
1312 category_list_on_top = aw->getClassName() ==
"CategoryListDialog";
1313 if (category_list_on_top) {
1319 main_menu.edit_item.setEnable(have_visible_items);
1320 main_menu.edit_category.setEnable(have_visible_categories || !all_item_list_on_top);
1321 main_menu.delete_item.setEnable(all_item_list_on_top && have_visible_items);
1322 main_menu.remove_item.setEnable(!all_item_list_on_top && have_visible_items);
1323 main_menu.delete_category.setEnable(!all_item_list_on_top || (category_list_on_top && have_visible_categories));
1324 main_menu.remove_checked_items.setEnable(!all_item_list_on_top && have_visible_items);
1325 main_menu.delete_checked_items.setEnable(all_item_list_on_top && have_visible_items);
1326 main_menu.check_items.setEnable(have_visible_items);
1327 main_menu.uncheck_items.setEnable(have_visible_items);
1328 main_menu.toggle_items.setEnable(have_visible_items);
1329 main_menu.copy_item.setEnable(have_visible_items);
1330 main_menu.copy_checked_items.setEnable(have_visible_items);
1336 switch(ev->getUserId()) {
Exception throw when a file is not found.
virtual const char * what() const override
Describes the exeption.
A pure virtual class acting as an interface for front-end implementations.
std::string filename
The current filename the Model was loaded from.
virtual void load_file(const std::string &filename)
Loads the specified file.
const std::shared_ptr< Category > get_category(int32_t id) const
Gets a Category by ID.
const std::shared_ptr< Item > get_item(int32_t id) const
Gets an Item by ID.
static const int32_t no_category
Indicates no filtering by category.
state_filter
Constants for filtering items depending on their checked state.
@ unchecked
Show only unchecked items.
@ all
Show all items, i.e. no filtering.
@ checked
Show only checked items.
Dialog for entering details of a Category.
std::shared_ptr< Category > category
void set_name(finalcut::FString name)
finalcut::FString get_name()
CategoryDialog(finalcut::FWidget *parent, KitListBaseApp *base_app, int32_t category_id)
void initLayout() override
KitListBaseApp * base_app
finalcut::FButton btn_cancel
finalcut::FLineEdit input_name
void adjustSize() override
virtual void onFocusIn(finalcut::FFocusEvent *ev) override
finalcut::FListBox * category_list
CategoryListDialog(finalcut::FWidget *parent, KitListBaseApp *base_app)
Constructor.
int32_t get_current_category_id()
KitListBaseApp * base_app
std::shared_ptr< Category > get_current_category()
void create_item_list_view(int32_t category_id)
void populate_category_list()
void show_current_item_category()
friend class KitListWindow
void adjustSize() override
void initLayout() override
Dialog for entering details of an Item.
KitListBaseApp * base_app
finalcut::FLineEdit input_name
void adjustSize() override
void initLayout() override
finalcut::FButton btn_cancel
void set_checked(bool checked)
std::shared_ptr< Item > item
finalcut::FString get_name()
finalcut::FCheckBox checkbox
ItemDialog(finalcut::FWidget *parent, KitListBaseApp *base_app, int32_t item_id)
void set_name(finalcut::FString name)
Displays a list of items, optionally for a specific Category.
void refresh_item_check_status(std::shared_ptr< Item > item)
void populate_item_list()
bool delete_current_item()
KitListBaseApp * base_app
ItemListDialog(finalcut::FWidget *parent, KitListBaseApp *base_app, int32_t category_id)
Constructor.
finalcut::FListView item_list_view
virtual void onFocusIn(finalcut::FFocusEvent *ev) override
void initLayout() override
int32_t get_category_id() const
void adjustSize() override
friend class KitListWindow
void remove_current_item()
int run(int argc, char *argv[], const std::string filename)
Runs the FINAL CUT text based user interface.
The application's main window.
CategoryListDialog * get_category_dialog()
void configure_window_menu()
void remove_item_list_dialog(int32_t removed_category)
void onClose(finalcut::FCloseEvent *) override
void update_checked_filter_state(Model::state_filter state)
friend class CategoryListDialog
finalcut::FStatusBar status_bar
ItemListDialog * get_item_dialog_for_category_id(int32_t category_id)
void on_view_checked_unchecked()
KitListBaseApp * base_app
void close_item_windows()
void on_delete_checked_items()
void on_delete_category()
finalcut::FMenuBar menu_bar
void on_copy_checked_items()
void configure_view_menu()
bool confirm_delete(std::shared_ptr< Category > category)
static void bring_to_front(finalcut::FWindow *window)
void configure_file_menu()
finalcut::FDialogListMenu window
void onUserEvent(finalcut::FUserEvent *ev) override
void configure_edit_menu()
KitListWindow(finalcut::FWidget *parent, KitListBaseApp *base_app)
Constuctor.
void refresh_item_dialogs()
void refresh_category_dialog()
void on_view_category_list()
void adjustSize() override
void on_remove_checked_items()
void on_view_all_items_list()
friend class ItemListDialog
Dialog to chose one or more categories.
finalcut::FButton btn_cancel
SelectCategoriesDialog(finalcut::FWidget *parent, KitListBaseApp *base_app)
void populate_select_category_list()
void adjustSize() override
finalcut::FListBox * category_list
KitListBaseApp * base_app
std::vector< int32_t > get_selected_category_ids()
void initLayout() override
A namespace for the FINALCUT user interface.