linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #02765
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2350: More efficient file list searches that start from the current selection
------------------------------------------------------------
revno: 2350
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Sat 2010-12-18 17:47:53 +0100
message:
More efficient file list searches that start from the current selection
modified:
changelog.txt
dcpp/DirectoryListing.h
win32/DirectoryListingFrame.cpp
win32/DirectoryListingFrame.h
--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk
Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt 2010-12-18 16:45:06 +0000
+++ changelog.txt 2010-12-18 16:47:53 +0000
@@ -34,6 +34,7 @@
* [ADC] Support hidden users as per the ADC ext spec (poy)
* [ADC] Group search extensions thanks to "SEGA" (poy)
* Keep search history in file list windows; add "Previous" button for backwards searching (emtee)
+* More efficient file list searches that start from the current selection (poy)
* Update OpenSSL to version 1.0.0c (poy)
* [L#378829] Make sure our OpenSSL binaries aren't "optimized for MS-DOS" (poy)
* [L#674545] Add magnet keyword search (thanks flow84)
=== modified file 'dcpp/DirectoryListing.h'
--- dcpp/DirectoryListing.h 2010-03-17 17:51:48 +0000
+++ dcpp/DirectoryListing.h 2010-12-18 16:47:53 +0000
@@ -68,7 +68,7 @@
GETSET(bool, adls, Adls);
};
- class Directory : public FastAlloc<Directory> {
+ class Directory : public FastAlloc<Directory>, boost::noncopyable {
public:
typedef Directory* Ptr;
struct DirSort {
@@ -112,10 +112,6 @@
GETSET(Directory*, parent, Parent);
GETSET(bool, adls, Adls);
GETSET(bool, complete, Complete);
-
- private:
- Directory(const Directory&);
- Directory& operator=(const Directory&);
};
class AdlDirectory : public Directory {
=== modified file 'win32/DirectoryListingFrame.cpp'
--- win32/DirectoryListingFrame.cpp 2010-12-11 18:16:14 +0000
+++ win32/DirectoryListingFrame.cpp 2010-12-18 16:47:53 +0000
@@ -183,7 +183,6 @@
usingDirMenu(false),
historyIndex(0),
treeRoot(NULL),
- skipHits(0),
updating(false),
searching(false)
{
@@ -323,9 +322,9 @@
SettingsManager::getInstance()->set(SettingsManager::DIRECTORYLISTINGFRAME_WIDTHS, WinUtil::toString(files->getColumnWidths()));
}
-void DirectoryListingFrame::handleFind(int direction) {
+void DirectoryListingFrame::handleFind(FindMode mode) {
searching = true;
- findFile(direction);
+ findFile(mode);
searching = false;
updateStatus();
}
@@ -725,8 +724,8 @@
void DirectoryListingFrame::selectItem(const tstring& name) {
HTREEITEM ht = findItem(treeRoot, name);
if(ht != NULL) {
+ dirs->setSelected(ht);
dirs->ensureVisible(ht);
- dirs->setSelected(ht);
}
}
@@ -851,147 +850,93 @@
}
}
-HTREEITEM DirectoryListingFrame::findFile(const StringSearch& str, HTREEITEM root,
- int &foundFile, int &skipHits)
-{
- // Check dir name for match
- DirectoryListing::Directory* dir = dirs->getData(root)->dir;
- if(str.match(dir->getName())) {
- if(skipHits == 0) {
- foundFile = -1;
- return root;
- } else {
- skipHits--;
- }
- }
-
- // Force list pane to contain files of current dir
- changeDir(dir);
-
- // Check file names in list pane
- for(size_t i = 0; i < files->size(); i++) {
- ItemInfo* ii = files->getData(i);
- if(ii->type == ItemInfo::FILE) {
- if(str.match(ii->file->getName())) {
- if(skipHits == 0) {
- foundFile = i;
- return root;
- } else {
- skipHits--;
- }
- }
- }
- }
-
- dcdebug("looking for directories...\n");
- // Check subdirs recursively
- HTREEITEM item = dirs->getChild(root);
- while(item != NULL) {
- HTREEITEM srch = findFile(str, item, foundFile, skipHits);
- if(srch)
- return srch;
- else
- item = dirs->getNextSibling(item);
- }
-
- return 0;
+pair<HTREEITEM, int> DirectoryListingFrame::findFile(const StringSearch& str, bool reverse, HTREEITEM item, int pos) {
+ // try to match the names currently in the list pane
+ const int n = files->size();
+ if(reverse && pos == -1)
+ pos = n;
+ for(reverse ? --pos : ++pos; reverse ? (pos >= 0) : (pos < n); reverse ? --pos : ++pos) {
+ const ItemInfo& ii = *files->getData(pos);
+ const string& name = (ii.type == ItemInfo::FILE) ? ii.file->getName() : ii.dir->getName();
+ if(str.match(name))
+ return make_pair(item, pos);
+ }
+
+ // flow to the next directory
+ HTREEITEM next = dirs->getNext(item, reverse ? TVGN_PREVIOUSVISIBLE : TVGN_NEXTVISIBLE);
+ if(next) {
+ if(dirs->getChild(next)) {
+ dirs->expand(next);
+ next = dirs->getNext(item, reverse ? TVGN_PREVIOUSVISIBLE : TVGN_NEXTVISIBLE);
+ }
+
+ // refresh the list pane to respect sorting etc
+ changeDir(dirs->getData(next)->dir);
+
+ return findFile(str, reverse, next, -1);
+ }
+
+ return make_pair(nullptr, 0);
}
-void DirectoryListingFrame::findFile(int direction)
-{
- if(findStr.empty() && direction != FIND_START) {
- direction = FIND_START;
- }
-
- switch (direction) {
- case FIND_START:
- {
+void DirectoryListingFrame::findFile(FindMode mode) {
+ if(mode == FIND_START || findStr.empty()) {
// Prompt for substring to find
- ParamDlg dlg(this, T_("Search for file"), T_("Enter search string"), lastSearches, 0, true /*comboBoxEdit*/);
-
+ ParamDlg dlg(this, T_("Search for file"), T_("Enter search string"), lastSearches, 0, true);
if(dlg.run() != IDOK)
return;
const tstring& value = dlg.getValue();
- if(!value.empty() && std::find(lastSearches.begin(), lastSearches.end(), value) == lastSearches.end()) {
+ if(value.empty())
+ return;
+ findStr = Text::fromT(value);
+
+ if(std::find(lastSearches.begin(), lastSearches.end(), value) == lastSearches.end()) {
size_t i = max(SETTING(SEARCH_HISTORY) - 1, 0);
while(lastSearches.size() > i) {
lastSearches.erase(lastSearches.end() - 1);
}
lastSearches.insert(lastSearches.begin(), value);
}
- findStr = Text::fromT(value);
- skipHits = 0;
- break;
- }
- case FIND_NEXT:
- skipHits++;
- break;
- case FIND_PREV:
- if (skipHits == 0) {
- dwt::MessageBox(this).show(T_("No matches"), T_("Find previous"));
- return;
- }
- skipHits--;
- }
-
- if(findStr.empty())
- return;
+ }
HoldRedraw hold(files);
HoldRedraw hold2(dirs);
HoldRedraw hold3(status);
// Do a search
- int foundFile = -1, skipHitsTmp = skipHits;
+
HTREEITEM const oldDir = dirs->getSelected();
- HTREEITEM const foundDir = findFile(StringSearch(findStr), treeRoot, foundFile, skipHitsTmp);
-
- if(foundDir) {
- // Highlight the directory tree and list if the parent dir/a matched dir was found
- if(foundFile >= 0) {
- // SelectItem won't update the list if SetRedraw was set to FALSE and then
- // to TRUE and the item setSelecteded is the same as the last one... workaround:
- if(oldDir == foundDir)
- dirs->setSelected(NULL);
-
- dirs->setSelected(foundDir);
- } else {
- // Got a dir; setSelected its parent directory in the tree if there is one
- HTREEITEM parentItem = dirs->getParent(foundDir);
- if(parentItem) {
- // Go to parent file list
- dirs->setSelected(parentItem);
-
- // Locate the dir in the file list
- DirectoryListing::Directory* dir = dirs->getData(foundDir)->dir;
-
- foundFile = files->find(Text::toT(dir->getName()), -1, false);
- } else {
- // If no parent exists, just the dir tree item and skip the list highlighting
- dirs->setSelected(foundDir);
- }
- }
-
- // Remove prev. setSelectedion from file list
- if(files->hasSelected()) {
- files->clearSelection();
- }
-
- // Highlight and focus the dir/file if possible
- if(foundFile >= 0) {
- files->setFocus();
- files->setSelected(foundFile);
- files->ensureVisible(foundFile);
- } else {
- dirs->setFocus();
- }
+
+ if(mode == FIND_START) {
+ dirs->setSelected(treeRoot);
+ files->clearSelection();
+ }
+
+ auto search = findFile(StringSearch(findStr), mode == FIND_PREV, (mode == FIND_START) ? treeRoot : oldDir, files->getSelected());
+
+ if(search.first) {
+ // SelectItem won't update the list if SetRedraw was set to FALSE and then
+ // to TRUE and the item setSelecteded is the same as the last one... workaround:
+ if(oldDir == search.first)
+ dirs->setSelected(NULL);
+ // Highlight the directory in the tree
+ dirs->setSelected(search.first);
+ dirs->ensureVisible(search.first);
+
+ // Remove prev. selection from file list
+ files->clearSelection();
+
+ // Highlight and focus the file
+ files->setFocus();
+ files->setSelected(search.second);
+ files->ensureVisible(search.second);
+
} else {
+ // same workaround as above (select NULL / select old dir) as dirs may have changed while searching
dirs->setSelected(NULL);
dirs->setSelected(oldDir);
- dwt::MessageBox(this).show(T_("No matches"), T_("Search for file"));
- if (skipHits > 0)
- skipHits--;
+ dwt::MessageBox(this).show(T_("No matches found for:") + _T("\n") + Text::toT(findStr), T_("Search for file"));
}
}
=== modified file 'win32/DirectoryListingFrame.h'
--- win32/DirectoryListingFrame.h 2010-12-11 18:16:14 +0000
+++ win32/DirectoryListingFrame.h 2010-12-18 16:47:53 +0000
@@ -88,12 +88,12 @@
COLUMN_LAST
};
- enum {
+ enum FindMode {
FIND_START,
FIND_NEXT,
FIND_PREV
};
-
+
class ItemInfo : public FastAlloc<ItemInfo> {
public:
enum ItemType {
@@ -186,7 +186,6 @@
string findStr;
string size;
- int skipHits;
bool updating;
bool searching;
@@ -217,7 +216,7 @@
void addShellPaths(const ShellMenuPtr& menu, const vector<ItemInfo*>& sel);
void addUserMenu(const MenuPtr& menu);
- void handleFind(int direction);
+ void handleFind(FindMode mode);
void handleListDiff();
void handleMatchQueue();
@@ -260,8 +259,8 @@
void initStatusText();
void updateStatus();
- void findFile(int direction);
- HTREEITEM findFile(const StringSearch& str, HTREEITEM root, int &foundFile, int &skipHits);
+ void findFile(FindMode mode);
+ pair<HTREEITEM, int> findFile(const StringSearch& str, bool reverse, HTREEITEM item, int pos);
// MDIChildFrame
void tabMenuImpl(dwt::MenuPtr& menu);