[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [kate] addons: Search and Replace plugin: search in "All Open Projects"
From:       Gregor Mi <codestruct () posteo ! org>
Date:       2014-11-30 19:03:51
Message-ID: E1Xv9mh-0004j2-PT () scm ! kde ! org
[Download RAW message or body]

Git commit a0daa7b08864c4422ad6d5806e2f6c9681bd58c5 by Gregor Mi.
Committed on 30/11/2014 at 19:03.
Pushed by gregormi into branch 'master'.

Search and Replace plugin: search in "All Open Projects"

REVIEW: 121290

- Project plugin:
- add two new Q_PROPERTYs: allProjectsCommonBaseDir and
allProjectsFiles
- add FileUtil::commonParent and add first unit test in Project plugin

- Search plugin:
- Change label from "Search:" to "Search in:" and adapt combobox
accordingly
- Add new entry "All Open Projects" to combobox

M  +4    -0    addons/project/CMakeLists.txt
A  +12   -0    addons/project/autotests/CMakeLists.txt
A  +43   -0    addons/project/autotests/test1.cpp     [License: LGPL (v2+)]
A  +40   -0    addons/project/autotests/test1.h     [License: LGPL (v2+)]
A  +41   -0    addons/project/fileutil.cpp     [License: LGPL (v2+)]
A  +42   -0    addons/project/fileutil.h     [License: LGPL (v2+)]
M  +33   -0    addons/project/kateprojectpluginview.cpp
M  +16   -0    addons/project/kateprojectpluginview.h
M  +43   -17   addons/search/plugin_search.cpp
M  +3    -3    addons/search/search.ui

http://commits.kde.org/kate/a0daa7b08864c4422ad6d5806e2f6c9681bd58c5

diff --git a/addons/project/CMakeLists.txt b/addons/project/CMakeLists.txt
index 8019f63..d693d83 100644
--- a/addons/project/CMakeLists.txt
+++ b/addons/project/CMakeLists.txt
@@ -11,6 +11,7 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
 
 add_definitions(-DTRANSLATION_DOMAIN=\"kateproject\")
 set(kateprojectplugin_PART_SRCS
+  fileutil.cpp
   kateprojectplugin.cpp
   kateprojectpluginview.cpp
   kateproject.cpp
@@ -45,3 +46,6 @@ install( FILES ui.rc DESTINATION  ${KXMLGUI_INSTALL_DIR}/kateproject )
 install( FILES kateproject.example DESTINATION  ${DATA_INSTALL_DIR}/kateproject )
 
 kcoreaddons_desktop_to_json (kateprojectplugin kateprojectplugin.desktop)
+
+############# unit tests ################
+ecm_optional_add_subdirectory (autotests)
diff --git a/addons/project/autotests/CMakeLists.txt b/addons/project/autotests/CMakeLists.txt
new file mode 100644
index 0000000..cb79a0d
--- /dev/null
+++ b/addons/project/autotests/CMakeLists.txt
@@ -0,0 +1,12 @@
+include(ECMMarkAsTest)
+
+include_directories(
+    ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+# Project Plugin
+set(ProjectPluginSrc test1.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../fileutil.cpp)
+add_executable(projectplugin_test ${ProjectPluginSrc})
+add_test(plugin-project_test projectplugin_test)
+target_link_libraries(projectplugin_test kdeinit_kate Qt5::Test)
+ecm_mark_as_test(projectplugin_test)
diff --git a/addons/project/autotests/test1.cpp b/addons/project/autotests/test1.cpp
new file mode 100644
index 0000000..0da8b18
--- /dev/null
+++ b/addons/project/autotests/test1.cpp
@@ -0,0 +1,43 @@
+/* This file is part of the KDE project
+ *
+ *  Copyright 2014 Gregor Mi <codestruct@posteo.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include "test1.h"
+#include "fileutil.h"
+
+#include <QtTest>
+
+QTEST_MAIN(Test1)
+
+void Test1::initTestCase()
+{
+}
+
+void Test1::cleanupTestCase()
+{
+}
+
+void Test1::testCommonParent()
+{
+    QCOMPARE(FileUtil::commonParent(QLatin1String("/usr/local/bin"), QLatin1String("/usr/local/bin")), \
QLatin1String("/usr/local/")); +    QCOMPARE(FileUtil::commonParent(QLatin1String("/usr/local"), \
QLatin1String("/usr/local/bin")), QLatin1String("/usr/")); +    \
QCOMPARE(FileUtil::commonParent(QLatin1String("~/dev/proj1"), QLatin1String("~/dev/proj222")), \
QLatin1String("~/dev/")); +}
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/addons/project/autotests/test1.h b/addons/project/autotests/test1.h
new file mode 100644
index 0000000..5d7faed
--- /dev/null
+++ b/addons/project/autotests/test1.h
@@ -0,0 +1,40 @@
+/* This file is part of the KDE project
+ *
+ *  Copyright 2014 Gregor Mi <codestruct@posteo.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KATE_PROJECT_TEST1_H
+#define KATE_PROJECT_TEST1_H
+
+#include <QObject>
+
+class Test1 : public QObject
+{
+    Q_OBJECT
+
+public Q_SLOTS:
+    void initTestCase();
+    void cleanupTestCase();
+
+private Q_SLOTS:
+    void testCommonParent();
+};
+
+#endif
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/addons/project/fileutil.cpp b/addons/project/fileutil.cpp
new file mode 100644
index 0000000..b16de80
--- /dev/null
+++ b/addons/project/fileutil.cpp
@@ -0,0 +1,41 @@
+/* This file is part of the KDE project
+ *
+ *  Copyright 2014 Gregor Mi <codestruct@posteo.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include "fileutil.h"
+
+// code taken from http://stackoverflow.com/questions/15713529/get-common-parent-of-2-qdir
+// note that there is unit test
+const QString FileUtil::commonParent(const QString& path1, const QString& path2)
+{
+    QString ret = path2;
+
+    while (!path1.startsWith(ret))
+        ret.chop(1);
+
+    if (ret.isEmpty())
+        return ret;
+
+    while (!ret.endsWith(QLatin1String("/")))
+        ret.chop(1);
+
+    return ret;
+}
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/addons/project/fileutil.h b/addons/project/fileutil.h
new file mode 100644
index 0000000..daa688c
--- /dev/null
+++ b/addons/project/fileutil.h
@@ -0,0 +1,42 @@
+/* This file is part of the KDE project
+ *
+ *  Copyright 2014 Gregor Mi <codestruct@posteo.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KATE_PROJECT_FILEUTIL_H
+#define KATE_PROJECT_FILEUTIL_H
+
+#include <QString>
+
+class FileUtil
+{
+public:
+    /**
+     * @Returns the common path of two paths. E.g.
+     * path1=/usr/local/bin
+     * path2=/usr/bin
+     * result=/usr
+     *
+     * TODO: Extend QUrl with this method and submit patch to QT
+     */
+    static const QString commonParent(const QString& path1, const QString& path2);
+};
+
+#endif
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/addons/project/kateprojectpluginview.cpp b/addons/project/kateprojectpluginview.cpp
index 60501c8..564c839 100644
--- a/addons/project/kateprojectpluginview.cpp
+++ b/addons/project/kateprojectpluginview.cpp
@@ -19,6 +19,7 @@
  */
 
 #include "kateprojectpluginview.h"
+#include "fileutil.h"
 
 #include <ktexteditor/editor.h>
 #include <ktexteditor/application.h>
@@ -255,6 +256,38 @@ QStringList KateProjectPluginView::projectFiles() const
     return active->project()->files();
 }
 
+QString KateProjectPluginView::allProjectsCommonBaseDir() const
+{
+    auto projects = m_plugin->projects();
+
+    if (projects.empty()) {
+        return QString();
+    }
+
+    if (projects.size() == 1) {
+        return projects[0]->baseDir();
+    }
+
+    QString commonParent1 = FileUtil::commonParent(projects[0]->baseDir(), projects[1]->baseDir());
+
+    for (int i = 2; i < projects.size(); i++) {
+        commonParent1 = FileUtil::commonParent(commonParent1, projects[i]->baseDir());
+    }
+
+    return commonParent1;
+}
+
+QStringList KateProjectPluginView::allProjectsFiles() const
+{
+    QStringList fileList;
+
+    foreach (auto project, m_plugin->projects()) {
+        fileList.append(project->files());
+    }
+
+    return fileList;
+}
+
 void KateProjectPluginView::slotViewChanged()
 {
     /**
diff --git a/addons/project/kateprojectpluginview.h b/addons/project/kateprojectpluginview.h
index d3674c1..60e7fe5 100644
--- a/addons/project/kateprojectpluginview.h
+++ b/addons/project/kateprojectpluginview.h
@@ -43,6 +43,9 @@ class KateProjectPluginView : public QObject, public KXMLGUIClient
     Q_PROPERTY(QVariantMap projectMap READ projectMap NOTIFY projectMapChanged)
     Q_PROPERTY(QStringList projectFiles READ projectFiles)
 
+    Q_PROPERTY(QString allProjectsCommonBaseDir READ allProjectsCommonBaseDir)
+    Q_PROPERTY(QStringList allProjectsFiles READ allProjectsFiles)
+
 public:
     KateProjectPluginView(KateProjectPlugin *plugin, KTextEditor::MainWindow *mainWindow);
     ~KateProjectPluginView();
@@ -76,6 +79,19 @@ public:
     QStringList projectFiles() const;
 
     /**
+     * Example: Two projects are loaded with baseDir1="/home/dev/project1" and
+     * baseDir2="/home/dev/project2". Then "/home/dev/" is returned.
+     * @see projectBaseDir().
+     * Used for the Search&Replace plugin for option "Search in all open projects".
+     */
+    QString allProjectsCommonBaseDir() const;
+
+    /**
+     * @returns a flat list of files for all open projects (@see also projectFiles())
+     */
+    QStringList allProjectsFiles() const;
+
+    /**
      * the main window we belong to
      * @return our main window
      */
diff --git a/addons/search/plugin_search.cpp b/addons/search/plugin_search.cpp
index 73c08ff..3b39131 100644
--- a/addons/search/plugin_search.cpp
+++ b/addons/search/plugin_search.cpp
@@ -613,11 +613,12 @@ void KatePluginSearchView::searchPlaceChanged()
     m_ui.displayOptions->setChecked(true);
 
     const bool inFolder = (m_ui.searchPlaceCombo->currentIndex() == 1);
-    const bool inProject = (m_ui.searchPlaceCombo->currentIndex() == 2);
+    const bool inCurrentProject = (m_ui.searchPlaceCombo->currentIndex() == 2);
+    const bool inAllOpenProjects = (m_ui.searchPlaceCombo->currentIndex() == 3);
 
-    m_ui.filterCombo->setEnabled(inFolder || inProject);
+    m_ui.filterCombo->setEnabled(inFolder || inCurrentProject || inAllOpenProjects);
 
-    m_ui.excludeCombo->setEnabled(inFolder || inProject);
+    m_ui.excludeCombo->setEnabled(inFolder || inCurrentProject || inAllOpenProjects);
     m_ui.folderRequester->setEnabled(inFolder);
     m_ui.folderUpButton->setEnabled(inFolder);
     m_ui.currentFolderButton->setEnabled(inFolder);
@@ -902,6 +903,9 @@ void KatePluginSearchView::startSearch()
     m_searchDiskFilesDone = false;
     m_searchOpenFilesDone = false;
 
+    const bool inCurrentProject = m_ui.searchPlaceCombo->currentIndex() == 2;
+    const bool inAllOpenProjects = m_ui.searchPlaceCombo->currentIndex() == 3;
+
     if (m_ui.searchPlaceCombo->currentIndex() ==  0) {
         m_searchDiskFilesDone = true;
         m_resultBaseDir.clear();
@@ -923,19 +927,29 @@ void KatePluginSearchView::startSearch()
                                        m_ui.excludeCombo->currentText());
         // the file list will be ready when the thread returns (connected to folderFileListChanged)
     }
-    else {
+    else if (inCurrentProject || inAllOpenProjects) {
         /**
          * init search with file list from current project, if any
          */
         m_resultBaseDir.clear();
         QStringList files;
-        QString projectName;
         if (m_projectPluginView) {
-            projectName = m_projectPluginView->property ("projectName").toString();
-            m_resultBaseDir = m_projectPluginView->property ("projectBaseDir").toString();
+            if (inCurrentProject) {
+                m_resultBaseDir = m_projectPluginView->property ("projectBaseDir").toString();
+            } else {
+                m_resultBaseDir = m_projectPluginView->property ("allProjectsCommonBaseDir").toString();
+            }
+
             if (!m_resultBaseDir.endsWith(QLatin1Char('/')))
                 m_resultBaseDir += QLatin1Char('/');
-            QStringList projectFiles = m_projectPluginView->property ("projectFiles").toStringList();
+
+            QStringList projectFiles;
+            if (inCurrentProject) {
+                projectFiles = m_projectPluginView->property ("projectFiles").toStringList();
+            } else {
+                projectFiles = m_projectPluginView->property ("allProjectsFiles").toStringList();
+            }
+
             files = filterFiles(projectFiles);
         }
         addHeaderItem();
@@ -953,11 +967,12 @@ void KatePluginSearchView::startSearch()
         // The DiskFile might finish immediately
         if (openList.size() > 0) {
             m_searchOpenFiles.startSearch(openList, m_curResults->regExp);
-        }
-        else {
+        } else {
             m_searchOpenFilesDone = true;
         }
         m_searchDiskFiles.startSearch(files, reg);
+    } else {
+        Q_ASSERT_X(false, "KatePluginSearchView::startSearch", "case not handled");
     }
 }
 
@@ -1076,14 +1091,22 @@ void KatePluginSearchView::searchDone()
                                                         m_resultBaseDir));
                 break;
             case 2:
-                QString projectName;
-                if (m_projectPluginView) {
-                    projectName = m_projectPluginView->property("projectName").toString();
+                {
+                    QString projectName;
+                    if (m_projectPluginView) {
+                        projectName = m_projectPluginView->property("projectName").toString();
+                    }
+                    root->setData(0, Qt::DisplayRole, i18np("<b><i>One match found in project %2 \
(%3)</i></b>", +                                                            "<b><i>%1 matches found in \
project %2 (%3)</i></b>", +                                                            \
m_curResults->matches, +                                                            projectName,
+                                                            m_resultBaseDir));
+                    break;
                 }
-                root->setData(0, Qt::DisplayRole, i18np("<b><i>One match found in project %2 \
                (%3)</i></b>",
-                                                        "<b><i>%1 matches found in project %2 \
(%3)</i></b>", +            case 3: // "in Open Projects"
+                root->setData(0, Qt::DisplayRole, i18np("<b><i>One match found in all open projects \
(common parent: %2)</i></b>", +                                                        "<b><i>%1 matches \
                found in all open projects (common parent: %2)</i></b>",
                                                         m_curResults->matches,
-                                                        projectName,
                                                         m_resultBaseDir));
                 break;
         }
@@ -1744,12 +1767,15 @@ void KatePluginSearchView::slotProjectFileNameChanged ()
     if (!projectFileName.isEmpty()) {
         if (m_ui.searchPlaceCombo->count() < 3) {
             // add "in Project"
-            m_ui.searchPlaceCombo->addItem (SmallIcon(QStringLiteral("project-open")), i18n("in \
Project")); +            m_ui.searchPlaceCombo->addItem (SmallIcon(QStringLiteral("project-open")), \
i18n("Current Project"));  if (m_switchToProjectModeWhenAvailable) {
                 // switch to search "in Project"
                 m_switchToProjectModeWhenAvailable = false;
                 setSearchPlace (2);
             }
+
+            // add "in Open Projects"
+            m_ui.searchPlaceCombo->addItem(SmallIcon(QStringLiteral("project-open")), i18n("All Open \
Projects"));  }
     }
 
diff --git a/addons/search/search.ui b/addons/search/search.ui
index 23c85b4..a5b9712 100644
--- a/addons/search/search.ui
+++ b/addons/search/search.ui
@@ -289,7 +289,7 @@
             <item>
              <widget class="QLabel" name="label">
               <property name="text">
-               <string>Se&amp;arch:</string>
+               <string>Se&amp;arch in:</string>
               </property>
               <property name="buddy">
                <cstring>searchPlaceCombo</cstring>
@@ -300,12 +300,12 @@
              <widget class="KComboBox" name="searchPlaceCombo">
               <item>
                <property name="text">
-                <string>in Open files</string>
+                <string>Open Files</string>
                </property>
               </item>
               <item>
                <property name="text">
-                <string>in Folder</string>
+                <string>Folder</string>
                </property>
               </item>
              </widget>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic