OSDN Git Service

Merge with stable
authorsdottaka <sdottaka@users.sourceforge.net>
Sun, 25 Jan 2015 06:21:54 +0000 (15:21 +0900)
committersdottaka <sdottaka@users.sourceforge.net>
Sun, 25 Jan 2015 06:21:54 +0000 (15:21 +0900)
1  2 
Src/DirActions.cpp
Src/DirView.cpp
Src/MainFrm.cpp

@@@ -543,225 -1356,44 +543,225 @@@ bool IsItemNavigableDiff(const CDiffCon
        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() && 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() && 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 *pdi[3],
 +              PathContext & paths, int & sel1, bool & isdir, int nPane[3], String& errmsg)
  {
 -      String left, right;
 -      if (!GetSelectedFileNames(left, right)) return _T("");
 -      return stype==SIDE_LEFT ? left : right;
 +      pdi[0] = &ctxt.GetDiffAt(pos1);
 +      pdi[1] = pdi[0];
 +      pdi[2] = pdi[0];
 +
 +      paths = GetItemFileNames(ctxt, *pdi[0]);
 +
 +      for (int nIndex = 0; nIndex < paths.GetSize(); ++nIndex)
 +              nPane[nIndex] = nIndex;
 +
 +      if (pdi[0]->diffcode.isDirectory())
 +              isdir = true;
 +
 +      if (isdir && (pdi[0]->diffcode.isExistsFirst() && pdi[1]->diffcode.isExistsSecond() && pdi[2]->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 *pdi[3],
 +              PathContext & paths, int & sel1, int & sel2, bool & isDir, int nPane[3], String& errmsg)
  {
 -      UINT_PTR diffpos = GetItemKey(sel);
 -      if (diffpos == (UINT_PTR)SPECIAL_ITEM_POS)
 +      String pathLeft, pathRight;
 +
 +      // Two items selected, get their info
 +      pdi[0] = &ctxt.GetDiffAt(pos1);
 +      pdi[1] = &ctxt.GetDiffAt(pos2);
 +      nPane[0] = 0;
 +      nPane[1] = 1;
 +
 +      // Check for binary & side compatibility & file/dir compatibility
 +      if (!AreItemsOpenable(ctxt, selectionType, *pdi[0], *pdi[1]))
        {
 -              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 (pdi[0]->diffcode.isSideSecondOnly() || (pdi[0]->diffcode.isSideBoth() &&
 +                              pdi[1]->diffcode.isSideFirstOnly()))
 +              {
 +                      std::swap(pdi[0], pdi[1]);
 +                      std::swap(sel1, sel2);
 +              }
 +              break;
 +      case SELECTIONTYPE_LEFT1LEFT2:
 +              nPane[0] = nPane[1] = 0;
 +              break;
 +      case SELECTIONTYPE_RIGHT1RIGHT2:
 +              nPane[0] = nPane[1] = 1;
 +              break;
 +      case SELECTIONTYPE_LEFT1RIGHT2:
 +              break;
 +      case SELECTIONTYPE_LEFT2RIGHT1:
 +              std::swap(pdi[0], pdi[1]);
 +              std::swap(sel1, sel2);
 +              break;
 +      }
 +
++      PathContext files1, files2;
++      files1 = GetItemFileNames(ctxt, *pdi[0]);
++      files2 = GetItemFileNames(ctxt, *pdi[1]);
++      paths.SetLeft(files1[nPane[0]]);
++      paths.SetRight(files2[nPane[1]]);
++
 +      if (pdi[0]->diffcode.isDirectory())
 +      {
 +              isDir = true;
-               if (GetPairComparability(PathContext(pathLeft, pathRight)) != IS_EXISTING_DIR)
++              if (GetPairComparability(paths) != IS_EXISTING_DIR)
 +              {
 +                      errmsg = _("The selected folder is invalid.");
 +                      return false;
 +              }
        }
-       PathContext files1, files2;
-       files1 = GetItemFileNames(ctxt, *pdi[0]);
-       files2 = GetItemFileNames(ctxt, *pdi[1]);
-       paths.SetLeft(files1[nPane[0]]);
-       paths.SetRight(files2[nPane[1]]);
 +
 +      return true;
  }
  
  /**
@@@ -843,73 -1411,14 +843,74 @@@ bool GetOpenThreeItems(const CDiffConte
        }
        else
        {
 -              const DIFFITEM & di = GetDocument()->GetDiffByKey(diffpos);
 -              for (int nIndex = 0; nIndex < GetDocument()->m_nDirs; nIndex++)
 +              // Three items selected, get their info
 +              pdi[0] = &ctxt.GetDiffAt(pos1);
 +              pdi[1] = &ctxt.GetDiffAt(pos2);
 +              pdi[2] = &ctxt.GetDiffAt(pos3);
 +
 +              // Check for binary & side compatibility & file/dir compatibility
 +              if (!::AreItemsOpenable(ctxt, *pdi[0], *pdi[1], *pdi[2]))
 +              {
 +                      return false;
 +              }
 +              // Ensure that pdi[0] is on left (swap if needed)
 +              if (pdi[0]->diffcode.isExists(0) && pdi[1]->diffcode.isExists(1) && pdi[2]->diffcode.isExists(2))
 +              {
 +              }
 +              else if (pdi[0]->diffcode.isExists(0) && pdi[1]->diffcode.isExists(2) && pdi[2]->diffcode.isExists(1))
                {
 -                      const String relpath = di.diffFileInfo[nIndex].GetFile();
 -                      const String & path = GetDocument()->GetBasePath(nIndex);
 -                      paths->SetPath(nIndex, paths_ConcatPath(path, relpath));
 +                      std::swap(pdi[1], pdi[2]);
 +                      std::swap(sel2, sel3);
                }
-               if (GetPairComparability(PathContext(pathLeft, pathMiddle, pathRight)) != IS_EXISTING_DIR)
 +              else if (pdi[0]->diffcode.isExists(1) && pdi[1]->diffcode.isExists(0) && pdi[2]->diffcode.isExists(2))
 +              {
 +                      std::swap(pdi[0], pdi[1]);
 +                      std::swap(sel1, sel2);
 +              }
 +              else if (pdi[0]->diffcode.isExists(1) && pdi[1]->diffcode.isExists(2) && pdi[2]->diffcode.isExists(0))
 +              {
 +                      std::swap(pdi[0], pdi[2]);
 +                      std::swap(sel1, sel3);
 +                      std::swap(pdi[1], pdi[2]);
 +                      std::swap(sel2, sel3);
 +              }
 +              else if (pdi[0]->diffcode.isExists(2) && pdi[1]->diffcode.isExists(0) && pdi[2]->diffcode.isExists(1))
 +              {
 +                      std::swap(pdi[0], pdi[1]);
 +                      std::swap(sel1, sel2);
 +                      std::swap(pdi[1], pdi[2]);
 +                      std::swap(sel2, sel3);
 +              }
 +              else if (pdi[0]->diffcode.isExists(2) && pdi[1]->diffcode.isExists(1) && pdi[2]->diffcode.isExists(0))
 +              {
 +                      std::swap(pdi[0], pdi[2]);
 +                      std::swap(sel1, sel3);
 +              }
 +      }
 +
 +      // Fill in pathLeft & & pathMiddle & pathRight
 +      PathContext pathsTemp = GetItemFileNames(ctxt, *pdi[0]);
 +      pathLeft = pathsTemp[0];
 +      pathsTemp = GetItemFileNames(ctxt, *pdi[1]);
 +      pathMiddle = pathsTemp[1];
 +      pathsTemp = GetItemFileNames(ctxt, *pdi[2]);
 +      pathRight = pathsTemp[2];
 +
++      paths.SetLeft(pathLeft.c_str());
++      paths.SetMiddle(pathMiddle.c_str());
++      paths.SetRight(pathRight.c_str());
++
 +      if (pdi[0]->diffcode.isDirectory())
 +      {
 +              isDir = true;
++              if (GetPairComparability(paths) != IS_EXISTING_DIR)
 +              {
 +                      errmsg = _("The selected folder is invalid.");
 +                      return false;
 +              } 
        }
-       paths.SetLeft(pathLeft.c_str());
-       paths.SetRight(pathRight.c_str());
 +
 +      return true;
  }
  
  /**
diff --cc Src/DirView.cpp
@@@ -1278,27 -1736,31 +1278,27 @@@ void CDirView::OpenSelection(SELECTIONT
  
        // Common variables which both code paths below are responsible for setting
        PathContext paths;
 -      DIFFITEM *pdi[3] = {0}; // left & right items (di1==di2 if single selection)
 +      const DIFFITEM *pdi[3] = {0}; // left & right items (di1==di2 if single selection)
        bool isdir = false; // set if we're comparing directories
 -      bool bRO[3] = { false, false, false };
        int nPane[3];
 -
 +      String errmsg;
 +      bool success;
-       if (pDoc->m_nDirs < 3 && pos2)
+       if (pos2 && !pos3)
 -      {
 -              bool success = OpenTwoItems(selectionType, pos1, pos2, pdi,
 -                              paths, sel1, sel2, isdir, nPane);
 -              if (!success)
 -                      return;
 -      }
 +              success = GetOpenTwoItems(ctxt, selectionType, pos1, pos2, pdi,
 +                              paths, sel1, sel2, isdir, nPane, errmsg);
-       else if (pDoc->m_nDirs == 3 && pos2)
+       else if (pos2 && pos3)
 -      {
 -              bool success = OpenThreeItems(pos1, pos2, pos3, pdi,
 -                              paths, sel1, sel2, sel3, isdir, nPane);
 -              if (!success)
 -                      return;
 -      }
 +              success = GetOpenThreeItems(ctxt, pos1, pos2, pos3, pdi,
 +                              paths, sel1, sel2, sel3, isdir, nPane, errmsg);
        else
 -      {
                // Only one item selected, so perform diff on its sides
 -              bool success = OpenOneItem(pos1, pdi, paths, sel1, isdir, nPane);
 +              success = GetOpenOneItem(ctxt, pos1, pdi, 
 +                              paths, sel1, isdir, nPane, errmsg);
                if (!success)
 -                      return;
 +      if (!success)
 +      {
 +              if (!errmsg.empty())
 +                      AfxMessageBox(errmsg.c_str(), MB_ICONSTOP);
 +              return;
        }
  
        // Now pathLeft, pathRight, di1, di2, and isdir are all set
        {
                // Open subfolders
                // Don't add folders to MRU
 -              GetMainFrame()->DoFileOpen(&paths, dwFlags, pDoc->GetRecursive(), (GetAsyncKeyState(VK_CONTROL) & 0x8000) ? NULL : pDoc);
 +              GetMainFrame()->DoFileOpen(&paths, dwFlags, GetDiffContext().m_bRecursive, (GetAsyncKeyState(VK_CONTROL) & 0x8000) ? NULL : pDoc);
        }
-       else if (HasZipSupport() && std::count_if(paths.begin(), paths.end(), ArchiveGuessFormat) == pDoc->m_nDirs)
+       else if (HasZipSupport() && std::count_if(paths.begin(), paths.end(), ArchiveGuessFormat) == paths.GetSize())
        {
                // Open archives, not adding paths to MRU
 -              GetMainFrame()->DoFileOpen(&paths, dwFlags, pDoc->GetRecursive(), NULL, _T(""), infoUnpacker);
 +              GetMainFrame()->DoFileOpen(&paths, dwFlags, GetDiffContext().m_bRecursive, NULL, _T(""), infoUnpacker);
        }
        else
        {
@@@ -1738,7 -2318,7 +1738,7 @@@ void CDirView::DoUpdateOpen(SELECTIONTY
                const DIFFITEM& di1 = GetDiffItem(sel1);
                const DIFFITEM& di2 = GetDiffItem(sel2);
                const DIFFITEM& di3 = GetDiffItem(sel3);
-               if (!::AreItemsOpenable(GetDiffContext(), di1, di2, di3))
 -              if (selectionType != SELECTIONTYPE_NORMAL || !AreItemsOpenable(di1, di2, di3))
++              if (selectionType != SELECTIONTYPE_NORMAL || !::AreItemsOpenable(GetDiffContext(), di1, di2, di3))
                {
                        pCmdUI->Enable(FALSE);
                        return;
diff --cc Src/MainFrm.cpp
Simple merge