# # # patch "guitone/src/view/InventoryView.cpp" # from [75865a2ee33160e4529cda5d8a587899e031c431] # to [429343b0120096ed5aff50c08e88b5b01a74e073] # # patch "guitone/src/view/InventoryView.h" # from [a69bbded6b9e82e8ed33f3dd090fc7c91fa8fc7d] # to [0ad2ef23cc24538fcd3fd656b712f7b6dca17e3e] # # patch "notes/TODO" # from [71fe4cab3a2662c480e6ab87c05210c83b1a54d7] # to [c29a50a4e625d4bf8141d38611668cfb26e0b05e] # ============================================================ --- guitone/src/view/InventoryView.cpp 75865a2ee33160e4529cda5d8a587899e031c431 +++ guitone/src/view/InventoryView.cpp 429343b0120096ed5aff50c08e88b5b01a74e073 @@ -100,6 +100,12 @@ InventoryView::~InventoryView() delete actFileDiff; delete actRevisionDiff; delete actRename; + delete actAddMultiple; + delete actRemoveMultiple; + delete actCommitMultiple; + delete actIgnoreMultiple; + delete actUnignoreMultiple; + delete actRevertMultiple; } // ensure that we only accept sortfilterproxymodels @@ -158,10 +164,10 @@ void InventoryView::slotContextMenuReque { qDebug("Selected indexes: %d", indexList.size()); + QMenu menu(this); + if (indexList.size() == 1) { - QMenu menu(this); - QModelIndex sourceIndex = static_cast(indexList[0].model())->mapToSource(indexList[0]); InventoryItem* item = static_cast(sourceIndex.internalPointer()); @@ -239,82 +245,160 @@ void InventoryView::slotContextMenuReque } } - // TODO: special items for directories to add/remove/commit/revert - // items in subdirectories via getStatusRecursive and friends - menu.exec(pos); } else { - // - // TODO: a smart multi-column menu could work like this: - // - // a) loop through all index items detecting the type of actions - // which could be executed on them - // b) create a menu which contains each action which can be at least - // executed on one item: - // - // |------------------| - // | Add (3 items) | - // | Ignore (2 items) | - // | ... | - // |------------------| - // - // Since we need to do that again later on when the actual action should - // take place, we might think about creating some kind of "temporary" - // selection which isn't visible (or some other "hack") but serves as - // input for the slot. - // - qDebug("No popup menu on multi-item selections yet."); + InventoryItem * item; + QModelIndex sourceIndex; + + QStringList actions; + actions << "add" << "drop" << "commit" + << "ignore" << "unignore" << "revert"; + + QMap actionMapping; + actionMapping.insert("add", actAddMultiple); + actionMapping.insert("drop", actRemoveMultiple); + actionMapping.insert("commit", actCommitMultiple); + actionMapping.insert("revert", actRevertMultiple); + actionMapping.insert("ignore", actIgnoreMultiple); + actionMapping.insert("unignore", actUnignoreMultiple); + + QMap actionCounter; + + foreach(QString action, actions) + { + actionCounter.insert(action, 0); + } + + foreach(QModelIndex index, indexList) + { + sourceIndex = + static_cast(index.model()) + ->mapToSource(index); + + item = static_cast(sourceIndex.internalPointer()); + + if (!item->isTracked()) + { + actionCounter["add"]++; + + if (item->hasStatus(InventoryItem::Unknown)) + { + actionCounter["ignore"]++; + } + else + { + actionCounter["unignore"]++; + } + continue; + } + + if (item->hasChangedRecursive()) + { + actionCounter["commit"]++; + actionCounter["revert"]++; + } + + actionCounter["drop"]++; + } + + QMapIterator i(actionCounter); + int totalItems = indexList.size(); + bool commonActions = false; + + while (i.hasNext()) + { + i.next(); + if (i.value() < totalItems) continue; + commonActions = true; + QAction * act = actionMapping[i.key()]; + act->setText(act->text().arg(totalItems)); + menu.addAction(act); + } + + if (!commonActions) + { + QAction * act = new QAction( + tr("No common action for selected items"), this + ); + menu.addAction(act); + } + + menu.exec(pos); return; } } void InventoryView::createAndConnectContextActions(void) { - actChdir = new QAction(tr("&Go into"), this); + actChdir = new QAction(tr("Go into"), this); actChdir->setStatusTip(tr("Go into the directory")); connect(actChdir, SIGNAL(triggered()), this, SLOT(slotChdir())); - actOpen = new QAction(tr("&Open"), this); + actOpen = new QAction(tr("Open"), this); actOpen->setStatusTip(tr("Open in default program")); connect(actOpen, SIGNAL(triggered()), this, SLOT(slotOpen())); - actAdd = new QAction(tr("&Add"), this); + actAdd = new QAction(tr("Add"), this); actAdd->setStatusTip(tr("Add to workspace")); connect(actAdd, SIGNAL(triggered()), this, SLOT(slotAdd())); - actRemove = new QAction(tr("&Remove"), this); + actRemove = new QAction(tr("Remove"), this); actRemove->setStatusTip(tr("Remove from workspace")); connect(actRemove, SIGNAL(triggered()), this, SLOT(slotRemove())); - actCommit = new QAction(tr("&Commit"), this); + actCommit = new QAction(tr("Commit"), this); actCommit->setStatusTip(tr("Commit")); connect(actCommit, SIGNAL(triggered()), this, SLOT(slotCommit())); - actIgnore = new QAction(tr("I&gnore"), this); + actIgnore = new QAction(tr("Ignore"), this); actIgnore->setStatusTip(tr("Ignore file")); connect(actIgnore, SIGNAL(triggered()), this, SLOT(slotIgnore())); - actUnignore = new QAction(tr("&Unignore"), this); + actUnignore = new QAction(tr("Unignore"), this); actUnignore->setStatusTip(tr("Unignore file")); connect(actUnignore, SIGNAL(triggered()), this, SLOT(slotUnignore())); - actRevert = new QAction(tr("R&evert"), this); + actRevert = new QAction(tr("Revert"), this); actRevert->setStatusTip(tr("Revert uncommitted changes")); connect(actRevert, SIGNAL(triggered()), this, SLOT(slotRevert())); - actFileDiff = new QAction(tr("D&iff"), this); + actFileDiff = new QAction(tr("Diff"), this); actFileDiff->setStatusTip(tr("Diff against base revision")); connect(actFileDiff, SIGNAL(triggered()), this, SLOT(slotFileDiff())); - actRevisionDiff = new QAction(tr("D&iff all"), this); + actRevisionDiff = new QAction(tr("Diff all"), this); actRevisionDiff->setStatusTip(tr("Show all differences")); connect(actRevisionDiff, SIGNAL(triggered()), this, SLOT(slotRevisionDiff())); - actRename = new QAction(tr("Rena&me"), this); + actRename = new QAction(tr("Rename"), this); actRename->setStatusTip(tr("Rename file")); connect(actRename, SIGNAL(triggered()), this, SLOT(slotRename())); + + actAddMultiple = new QAction(tr("Add %1 items"), this); + actAddMultiple->setStatusTip(tr("Add multiple files")); + connect(actAddMultiple, SIGNAL(triggered()), this, SLOT(slotAdd())); + + actRemoveMultiple = new QAction(tr("Remove %1 items"), this); + actRemoveMultiple->setStatusTip(tr("Remove multiple files")); + connect(actRemoveMultiple, SIGNAL(triggered()), this, SLOT(slotRemove())); + + actCommitMultiple = new QAction(tr("Commit %1 items"), this); + actCommitMultiple->setStatusTip(tr("Commit multiple files")); + connect(actCommitMultiple, SIGNAL(triggered()), this, SLOT(slotCommit())); + + actIgnoreMultiple = new QAction(tr("Ignore %1 items"), this); + actIgnoreMultiple->setStatusTip(tr("Ignore multiple files")); + connect(actIgnoreMultiple, SIGNAL(triggered()), this, SLOT(slotIgnore())); + + actUnignoreMultiple = new QAction(tr("Unignore %1 items"), this); + actUnignoreMultiple->setStatusTip(tr("Unignore multiple files")); + connect(actUnignoreMultiple, SIGNAL(triggered()), this, SLOT(slotUnignore())); + + actRevertMultiple = new QAction(tr("Revert %1 items"), this); + actRevertMultiple->setStatusTip(tr("Revert multiple files")); + connect(actRevertMultiple, SIGNAL(triggered()), this, SLOT(slotRevert())); } void InventoryView::slotChdir() ============================================================ --- guitone/src/view/InventoryView.h a69bbded6b9e82e8ed33f3dd090fc7c91fa8fc7d +++ guitone/src/view/InventoryView.h 0ad2ef23cc24538fcd3fd656b712f7b6dca17e3e @@ -51,18 +51,25 @@ private: void closeEvent(void); QModelIndex getSingleSelection(bool mapToSource = true); - QAction *actChdir; - QAction *actOpen; - QAction *actAdd; - QAction *actRemove; - QAction *actCommit; - QAction *actIgnore; - QAction *actUnignore; - QAction *actRevert; - QAction *actRename; - QAction *actFileDiff; - QAction *actRevisionDiff; - + QAction * actChdir; + QAction * actOpen; + QAction * actAdd; + QAction * actRemove; + QAction * actCommit; + QAction * actIgnore; + QAction * actUnignore; + QAction * actRevert; + QAction * actRename; + QAction * actFileDiff; + QAction * actRevisionDiff; + + QAction * actAddMultiple; + QAction * actRemoveMultiple; + QAction * actCommitMultiple; + QAction * actIgnoreMultiple; + QAction * actUnignoreMultiple; + QAction * actRevertMultiple; + Type type; InventoryViewDelegate invViewDelegate; ============================================================ --- notes/TODO 71fe4cab3a2662c480e6ab87c05210c83b1a54d7 +++ notes/TODO c29a50a4e625d4bf8141d38611668cfb26e0b05e @@ -1,6 +1,5 @@ Current TODO, for "long-term" stuff see Current TODO, for "long-term" stuff see IDEAS: -* implement smart multiple file/folder selections (stubs) * implement drag and drop (stubs) * fix rename behaviour for circular renames (no doubled items) * finish file exporter for exporting files from (partial) manifests