return true;
}
-/// get the file names on both sides for first selected item
-bool CDirView::GetSelectedFileNames(String& strLeft, String& strRight) const
+bool IsItemExistAll(const CDiffContext& ctxt, const DIFFITEM & di)
{
- int sel = m_pList->GetNextItem(-1, LVNI_SELECTED);
- if (sel == -1)
+ // Not a valid diffitem, one of special items (e.g "..")
+ if (di.diffcode.diffcode == 0)
return false;
- GetItemFileNames(sel, strLeft, strRight);
+ if (ctxt.GetCompareDirs() == 2)
+ return di.diffcode.isSideBoth();
+ else
+ return di.diffcode.isSideAll();
+}
+
+
+/**
+ * @brief Determines if the user wants to see given item.
+ * This function determines what items to show and what items to hide. There
+ * are lots of combinations, but basically we check if menuitem is enabled or
+ * disabled and show/hide matching items. For non-recursive compare we never
+ * hide folders as that would disable user browsing into them. And we even
+ * don't really know if folders are identical or different as we haven't
+ * compared them.
+ * @param [in] di Item to check.
+ * @return true if item should be shown, false if not.
+ * @sa CDirDoc::Redisplay()
+ */
+bool IsShowable(const CDiffContext& ctxt, const DIFFITEM & di, const DirViewFilterSettings& filter)
+{
+ if (di.customFlags1 & ViewCustomFlags::HIDDEN)
+ return false;
+
+ if (di.diffcode.isResultFiltered())
+ {
+ // Treat SKIPPED as a 'super'-flag. If item is skipped and user
+ // wants to see skipped items show item regardless of other flags
+ return filter.show_skipped;
+ }
+
+ if (di.diffcode.isDirectory())
+ {
+ // Subfolders in non-recursive compare can only be skipped or unique
+ if (!ctxt.m_bRecursive)
+ {
+ // left/right filters
+ if (di.diffcode.isSideFirstOnly() && !filter.show_unique_left)
+ return false;
+ if (di.diffcode.isSideSecondOnly() && !filter.show_unique_right)
+ return false;
+
+ // result filters
- if (di.diffcode.isResultError() /*&& !GetMainFrame()->m_bShowErrors FIXME:*/)
++ if (di.diffcode.isResultError() && FALSE/* !GetMainFrame()->m_bShowErrors FIXME:*/)
+ return false;
+ }
+ else // recursive mode (including tree-mode)
+ {
+ // left/right filters
+ if (di.diffcode.isSideFirstOnly() && !filter.show_unique_left)
+ return false;
+ if (di.diffcode.isSideSecondOnly() && !filter.show_unique_right)
+ return false;
+
+ // ONLY filter folders by result (identical/different) for tree-view.
+ // In the tree-view we show subfolders with identical/different
+ // status. The flat view only shows files inside folders. So if we
+ // filter by status the files inside folder are filtered too and
+ // users see files appearing/disappearing without clear logic.
+ if (filter.tree_mode)
+ {
+ // result filters
- if (di.diffcode.isResultError()/* && !GetMainFrame()->m_bShowErrors FIXME:*/)
++ if (di.diffcode.isResultError() && FALSE/* !GetMainFrame()->m_bShowErrors FIXME:*/)
+ return false;
+
+ // result filters
+ if (di.diffcode.isResultSame() && !filter.show_identical)
+ return false;
+ if (di.diffcode.isResultDiff() && !filter.show_different)
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // left/right filters
+ if (di.diffcode.isSideFirstOnly() && !filter.show_unique_left)
+ return false;
+ if (di.diffcode.isSideSecondOnly() && !filter.show_unique_right)
+ return false;
+
+ // file type filters
+ if (di.diffcode.isBin() && !filter.show_binaries)
+ return false;
+
+ // result filters
+ if (di.diffcode.isResultSame() && !filter.show_identical)
+ return false;
+ if (di.diffcode.isResultError() /* && !GetMainFrame()->m_bShowErrors FIXME:*/)
+ return false;
+ if (di.diffcode.isResultDiff() && !filter.show_different)
+ return false;
+ }
return true;
}
-/// get file name on specified side for first selected item
-String CDirView::GetSelectedFileName(SIDE_TYPE stype) const
+
+/**
+ * @brief Open one selected item.
+ * @param [in] pos1 Item position.
+ * @param [in,out] di1 Pointer to first diffitem.
+ * @param [in,out] di2 Pointer to second diffitem.
+ * @param [in,out] di3 Pointer to third diffitem.
+ * @param [out] paths First/Second/Third paths.
+ * @param [out] sel1 Item's selection index in listview.
+ * @param [in,out] isDir Is item folder?
+ * return false if there was error or item was completely processed.
+ */
+bool GetOpenOneItem(const CDiffContext& ctxt, uintptr_t pos1, const DIFFITEM **di1, const DIFFITEM **di2, const DIFFITEM **di3,
+ PathContext & paths, int & sel1, bool & isdir, String& errmsg)
{
- String left, right;
- if (!GetSelectedFileNames(left, right)) return _T("");
- return stype==SIDE_LEFT ? left : right;
+ *di1 = &ctxt.GetDiffAt(pos1);
+ *di2 = *di1;
+ *di3 = *di1;
+
+ paths = GetItemFileNames(ctxt, **di1);
+
+ if ((*di1)->diffcode.isDirectory())
+ isdir = true;
+
+ if (isdir && ((*di1)->diffcode.isExistsFirst() && (*di1)->diffcode.isExistsSecond() && (*di1)->diffcode.isExistsThird()))
+ {
+ // Check both folders exist. If either folder is missing that means
+ // folder has been changed behind our back, so we just tell user to
+ // refresh the compare.
+ PATH_EXISTENCE path1Exists = paths_DoesPathExist(paths[0]);
+ PATH_EXISTENCE path2Exists = paths_DoesPathExist(paths[1]);
+ if (path1Exists != IS_EXISTING_DIR || path2Exists != IS_EXISTING_DIR)
+ {
+ String invalid = path1Exists == IS_EXISTING_DIR ? paths[0] : paths[1];
+ errmsg = string_format_string1(
+ _("Operation aborted!\n\nFolder contents at disks has changed, path\n%1\nwas not found.\n\nPlease refresh the compare."),
+ invalid);
+ return false;
+ }
+ }
+
+ return true;
}
+
/**
- * @brief Get the file names on both sides for specified item.
- * @note Return empty strings if item is special item.
+ * @brief Open two selected items.
+ * @param [in] pos1 First item position.
+ * @param [in] pos2 Second item position.
+ * @param [in,out] di1 Pointer to first diffitem.
+ * @param [in,out] di2 Pointer to second diffitem.
+ * @param [out] paths First/Second/Third paths.
+ * @param [out] sel1 First item's selection index in listview.
+ * @param [out] sel2 Second item's selection index in listview.
+ * @param [in,out] isDir Is item folder?
+ * return false if there was error or item was completely processed.
*/
-void CDirView::GetItemFileNames(int sel, String& strLeft, String& strRight) const
+bool GetOpenTwoItems(const CDiffContext& ctxt, SELECTIONTYPE selectionType, uintptr_t pos1, uintptr_t pos2, const DIFFITEM **di1, const DIFFITEM **di2,
+ PathContext & paths, int & sel1, int & sel2, bool & isDir, String& errmsg)
{
- UINT_PTR diffpos = GetItemKey(sel);
- if (diffpos == (UINT_PTR)SPECIAL_ITEM_POS)
+ String pathLeft, pathRight;
+
+ // Two items selected, get their info
+ *di1 = &ctxt.GetDiffAt(pos1);
+ *di2 = &ctxt.GetDiffAt(pos2);
+
+ // Check for binary & side compatibility & file/dir compatibility
+ if (!AreItemsOpenable(ctxt, selectionType, **di1, **di2))
{
- strLeft.erase();
- strRight.erase();
+ return false;
}
- else
+
+ String temp;
+ switch (selectionType)
{
- const DIFFITEM & di = GetDocument()->GetDiffByKey(diffpos);
- const String leftrelpath = di.diffFileInfo[0].GetFile();
- const String rightrelpath = di.diffFileInfo[1].GetFile();
- const String & leftpath = GetDocument()->GetBasePath(0);
- const String & rightpath = GetDocument()->GetBasePath(1);
- strLeft = paths_ConcatPath(leftpath, leftrelpath);
- strRight = paths_ConcatPath(rightpath, rightrelpath);
+ case SELECTIONTYPE_NORMAL:
+ // Ensure that di1 is on left (swap if needed)
+ if ((*di1)->diffcode.isSideSecondOnly() || ((*di1)->diffcode.isSideBoth() &&
+ (*di2)->diffcode.isSideFirstOnly()))
+ {
+ const DIFFITEM * temp = *di1;
+ *di1 = *di2;
+ *di2 = temp;
+ int num = sel1;
+ sel1 = sel2;
+ sel2 = num;
+ }
+ // Fill in pathLeft & pathRight
+ GetItemFileNames(ctxt, **di1, pathLeft, temp);
+ GetItemFileNames(ctxt, **di2, temp, pathRight);
+ break;
+ case SELECTIONTYPE_LEFT1LEFT2:
+ GetItemFileNames(ctxt, **di1, pathLeft, temp);
+ GetItemFileNames(ctxt, **di2, pathRight, temp);
+ break;
+ case SELECTIONTYPE_RIGHT1RIGHT2:
+ GetItemFileNames(ctxt, **di1, temp, pathLeft);
+ GetItemFileNames(ctxt, **di2, temp, pathRight);
+ break;
+ case SELECTIONTYPE_LEFT1RIGHT2:
+ GetItemFileNames(ctxt, **di1, pathLeft, temp);
+ GetItemFileNames(ctxt, **di2, temp, pathRight);
+ break;
+ case SELECTIONTYPE_LEFT2RIGHT1:
+ GetItemFileNames(ctxt, **di1, temp, pathRight);
+ GetItemFileNames(ctxt, **di2, pathLeft, temp);
+ break;
+ }
+
+ if ((*di1)->diffcode.isDirectory())
+ {
+ isDir = true;
+ if (GetPairComparability(PathContext(pathLeft, pathRight)) != IS_EXISTING_DIR)
+ {
+ errmsg = _("The selected folder is invalid.");
+ return false;
+ }
}
+
+ paths.SetLeft(pathLeft);
+ paths.SetRight(pathRight);
+
+ return true;
}
/**