SpotLight

Paisible.frPaisible.fr Membre
13:59 modifié dans API AppKit #1
Bonjour,

Je souhaiterais ajouter une fonction à  mon application qui consisterais effectuer une recherche sur un mot dans un dossier de fichier HTML. La recherche se ferais sur le contenu et pas sur le code html.

Je sais faire une recherche de texte en passant par les APIs de webKit, il me suffirais alors d'itérer sur toutes les pages HTML du dossier. ça pourrais fonctionner mais cela ne me semble pas très propre.

L'autre solution à  laquelle je pensais été d'utiliser SpotLight qui me semble bien plus approprié. Malheureusement après bien des recherches je n'ai pas réussi à  comprendre son fonctionnement. Tous ce que j'ai trouvé me parait fort complexe par rapport à  mes besoins : gestion de threads, etc... qui me sont inutiles.

Quelqu'un aurait-il un exemple qui ferait la recherche d'un mot sur les fichiers d'un dossier sans thread etc... ?

Merci

Réponses

  • ChachaChacha Membre
    13:59 modifié #2
    Salut,

    ça n'est pas si compliqué !
    Basiquement,
    MDQueryCreate crée la recherche à  effectuer
    MDQuerySetSearchScope définit les emplacements de recherche
    MDQueryExecute la lance
    Et tu peux intercepter la progression avec des notifications.
    Mais dans ton cas, tu peux aussi utiliser l'option kMDQuerySynchronous pour le MDQueryExecute, qui permet de ne pas effectuer le travail en tâche de fond, mais d'attendre le résultat !

    Essaye donc un peu de bricoler avec ces fonctions, tu devrais vite obtenir un résultat.

    +
    Chacha
  • Paisible.frPaisible.fr Membre
    octobre 2008 modifié #3
    Merci chacha,

    Voila une réponse fort utile et qui me permettra de débrouissaler le terrain.
    Maintenant je sais dans quelle direction chercher.

    Sinon :
    1) La recherche spotlight fonctionnera t'elle sur les fichiers contenu à  l'intérieur du bundle de l'application ?

    2) Si je recherche dans la doc d'apple (ADC), toutes mes requêtes sur MDQueryCreate me donnent des pages indiquant que l'API est en carbon. C'est vraiment le cas ou c'est moi qui ne suit pas foutu de faire la bonne recherche ?
  • AliGatorAliGator Membre, Modérateur
    13:59 modifié #4
    Sans même connaà®tre ces fonctions spotlight, vu le nom, c'est clairement du Carbon oui.
    Il y a de toute façon 2 grandes API sous OSX, le framework Cocoa qui utilise comme langage l'Objective-C, et Carbon, qui utilise le langage C. D'ailleurs Cocoa n'est en fait qu'une surcouche de Carbon en général, un wrapper en Objective-C autour des méthodes Carbon en C.
    Quand tu vois dans la doc des trucs comme
    MDQueryRef MDQueryCreate (<br />&nbsp;  CFAllocatorRef allocator,<br />&nbsp;  CFStringRef queryString,<br />&nbsp;  CFArrayRef valueListAttrs,<br />&nbsp;  CFArrayRef sortingAttrs<br />);
    
    tu vois bien que c'est du C (un type de retour + un nom de fonction + "(" + liste des paramètres (type+nom) + ")") et non de l'Objective-C (les types seraient entre parenthèses, les arguments auraient des noms avec ":" à  la fin, etc) et que les types d'arguments sont CFxxx autrement dit des types CoreFoundation. C'est donc typiquement du C (API Carbon) et non de l'Objective-C (API Cocoa)*.
    De plus avec des noms de méthode comme ça ("xxxCreate") on reconnait la patte de l'API Carbon ici aussi.

    Alors certes, c'est déroutant, perso je suis pas fan de Carbon non plus et préfère Cocoa et le langage Objective-C. Mais comme dans ce cas il n'y a pas de surcouche/wrapper en Objective-C pour l'API de Spotlight, ben il faut bien se mettre à  Carbon. Et en regardant 2-3 exemples au final c'est pas sorcier et on arrive à  s'en sortir :P


    * Bon y'a pas que c'est cas, je stéréotype un peu mais bon
  • Paisible.frPaisible.fr Membre
    13:59 modifié #5
    Bon c'est pas mal du tout. :o
    Sauf que j'arrive pas à  construire le MDQuerySetSearchScope comme je le souhaite.

    En effet l'API est la suivante :
    <br />void MDQuerySetSearchScope (<br />&nbsp;  MDQueryRef query,<br />&nbsp;  CFArrayRef scopeDirectories,<br />&nbsp;  OptionBits scopeOptions<br />);<br />
    


    Et il est spécifié que :
    scopeDirectories : A CFArray of CFStringRef or CFURLRef objects which specify where to search. For convenience the kMDQueryScopeHome, kMDQueryScopeComputer and kMDQueryScopeNetwork constants may also be included in the array.


    Mon problème est que je n'arrive pas à  construire cette foutue CFArray of CFStringRef avec deux ou trois chemins de type "/Users/toto/blabla/patati/patata". :crackboom:-

    Mon dieu, vivement Leopard Snow qu'ils nous retirent ces couches Carbon du finder  >:)
  • AliGatorAliGator Membre, Modérateur
    13:59 modifié #6
    SnowLeopard ne retirera pas Carbon, je ne pense pas. Je pense même que Carbon restera toujours là , ce sont les API sur lesquelles CoreFoundation se basent si je ne m'abuse... Après peut-être Snow Leopard ajoutera-t-il des wrapper Cocoa pour ces APIs. Et là  en effet ça sera plus sympa pour manipuler tout ça.

    En attendant pour ton problème, je crois que CFArray et NSArray sont toll-free-bridged, de même que NSString* et CFStringRef, il me semble (bon, à  vérifier, mais ça ne m'étonnerait pas trop).
    Du coup si c'est bien le cas, créer un NSArray de NSString et le caster en CFArray ensuite te simplifierai la tâche de création ;)
  • Paisible.frPaisible.fr Membre
    13:59 modifié #7
    Merci Aligator grâce à  toi j'ai réussi à  faire mon tableau "CFArray of CFStringRef".

    Par contre bizzarement le code si dessous ne fonctionne pas :
    MDQueryRef queryRef = MDQueryCreate(CFAllocatorGetDefault(),<br />	CFSTR(&quot;kMDItemDisplayName = &#39;*.htm&#39; &amp;&amp; kMDItemTextContent = &#39;bonjour&#39;&quot;),<br />				(CFArrayRef)[NSArray arrayWithObject:(NSString *)kMDItemPath],<br />				NULL);<br />
    


    Alors que le code suivant oui :

    <br />MDQueryRef queryRef = MDQueryCreate(CFAllocatorGetDefault(),<br />	CFSTR(&quot;kMDItemDisplayName = &#39;*.htm&#39;&quot;),<br />				<br />				(CFArrayRef)[NSArray arrayWithObject:(NSString *)kMDItemPath],<br />				NULL);<br />
    


    Il semble que la recherche textuelle ne fonctionne pas pour les fichiers à  l'intérieur du bundle.
    Si fait le meme test en mettant le dossier à  l'extérieur ca fonctionne apparemment.

    Quelqu'un peut confirmer / infirmer ?

    Cela n'ennuie fortement car si c'est confirmé cela fout en l'air ma fonction de recherche.

  • AliGatorAliGator Membre, Modérateur
    13:59 modifié #8
    Je suis pas sûr de pouvoir confirmer à  100% mais en même temps ça ne m'étonnerait pas du tout qu'il ne scanne pas dans les Bundles.
    Il ne faut pas oublier que Spotlight se sert d'une base d'indexation pour... indexer les métadonnées associées à  tes fichiers (nom, contenu, type, durée des médias, ...). Il exécute ensuite sa recherche sur cette base d'indexation, donc dans sa base de données de ces metadatas.

    Donc tout ce que tu lui as demandé explicitement de ne pas indexer, dans les préférences spotlight, il ne l'indexera pas. De même pour les fichiers système qu'il n'indexe pas... et de même pour le contenu des bundles !

    Peut-être y a-t-il cependant une possibilité via l'API de demander d'indexer le contenu de ton/tes bundles ?
  • Paisible.frPaisible.fr Membre
    13:59 modifié #9
    Merci pour ces précisions.

    Quelques remarques/reflexions :
    1) Je pense que j'ai commis une erreur sur l'égalité, il semblerais qu'il faut utiliser un double egal comme operateru pour le kMDItemTextContent si je m'en tient à  la doc d'Apple. Je vais tester ce soir.

    2) Je n'ai rien trouvé me permettant de "forcer" l'indexation d'un dossier/fichier donné. Pourtant il me semblait avoir vu une ligne de commande, mais j'ai peut-être révé

    3) Si je ne peux effectuer une recherche spotlight textuel sur un ensemble de fichier dans mon bundle cela va fortement me decevoir et m'amener à  chercher une autre solution qui sera forcement mois élegante. Ce serait dommage...
  • NoNo Membre
    13:59 modifié #10
    dans 1223886953:

    Sans même connaà®tre ces fonctions spotlight, vu le nom, c'est clairement du Carbon oui.
    Il y a de toute façon 2 grandes API sous OSX, le framework Cocoa qui utilise comme langage l'Objective-C, et Carbon, qui utilise le langage C.
    [...]
    Alors certes, c'est déroutant, perso je suis pas fan de Carbon non plus et préfère Cocoa et le langage Objective-C. Mais comme dans ce cas il n'y a pas de surcouche/wrapper en Objective-C pour l'API de Spotlight, ben il faut bien se mettre à  Carbon. Et en regardant 2-3 exemples au final c'est pas sorcier et on arrive à  s'en sortir :P

    C'est bizarre, j'étais persuadé que Spotlight était accessible sous cocoa via les classes NSMetadata...
  • Paisible.frPaisible.fr Membre
    13:59 modifié #11
    dans 1223969350:
    C'est bizarre, j'étais persuadé que Spotlight était accessible sous cocoa via les classes NSMetadata...


    Effectivement, il semblerait que tu soit dans le vrai No :
    The NSMetadataQuery class encapsulates the functionality provided by the MDQuery opaque type for querying the Spotlight metadata.


    C'est une bonne nouvelle, mais cela résoud en rien mon problème de pouvoir lancer une recherche textuel sur des fichiers stockés à  l'interieur du bundle de mon application  :-\\
  • NoNo Membre
    13:59 modifié #12
    dans 1223969704:

    C'est une bonne nouvelle, mais cela résoud en rien mon problème de pouvoir lancer une recherche textuel sur des fichiers stockés à  l'interieur du bundle de mon application  :-\\


    Si j'ai tout compris tu cherches à  faire une recherche dans des fichiers html stockés quelque part dans ton bundle application...

    Peut être peux tu contourner la limitation de Spotlight en copiant ces html autre part au 1er lancement de ton appli (comme dans Application Support par exemple)...
    Sinon, tu peux aussi essayer de créer ton propre mdimporter : un plugin spécifique à  ton appli qui indexerai ton bundle...
  • Paisible.frPaisible.fr Membre
    13:59 modifié #13
    dans 1223970791:

    Si j'ai tout compris tu cherches à  faire une recherche dans des fichiers html stockés quelque part dans ton bundle application...

    Tu as parfaitement bien tout compris  :adios!:

    dans 1223970791:

    Peut être peux tu contourner la limitation de Spotlight en copiant ces html autre part au 1er lancement de ton appli (comme dans Application Support par exemple)...

    J'y ai bien pensé figure toi, mais :
    1) c'est pas très "élegant"
    2) je suis pas sur que "application support" soit le meilleur endroit pour cela. Quoique ...

    dans 1223970791:

    Sinon, tu peux aussi essayer de créer ton propre mdimporter : un plugin spécifique à  ton appli qui indexerai ton bundle...

    Oui effectivement, mais :
    1) Je trouve dommage de recoder quelque chose alors que SpotLight à  déjà  un MDImporter pour le HTML
    2) Cela ne m'à  pas l'air simple à  faire. Enfin, du moins cela semble representer un certain investissement
  • NoNo Membre
    octobre 2008 modifié #14
    On peut toujours essayer de forcer l'indexation d'un fichier par la commande mdimport, mais est ce que cela va fonctionner à  l'intérieur d'un .app ?

    Tente de faire l'expérience en forçant l'indexation d'un fichier html dans ton bundle, puis un coup de spotlight afin de voir si l'indexation est ok.

    Exemple dans le terminal :
    [tt]mdimport /Applications/monApplication.app/Contents/Resources/html/unFichier.html[/tt]
    (pour indexer le fichier unFichier.html se trouvant dans un répertoire html lui même dans les ressources de l'appli).

    Après quoi, si ça marche, Une série de NSTask au premier lancement de ton appli devrait faire l'affaire.
    Mieux, faudrait aussi tester si mdimport supporte de ne mettre que le chemin d'un répertoire afin d'indexer tous les fichiers s'y trouvant...
  • AliGatorAliGator Membre, Modérateur
    13:59 modifié #15
    Oui, le revers de la médaille (mais remarque ça peut ceci dit être une bonne chose, faut juste savoir si ça te dérange ou pas) c'est que si tu indexes le contenu de ton bundle avec Spotlight, ça va rajouter les données indexées à  la base spotlight globale... donc si l'utilisateur fait une recherche même hors de ton soft, en utilisant le menu Spotlight dans la barre de menus, genre depuis le Finder, il pourra tout aussi bien trouver le contenu de ton HTML dans ses résultats.
    Reste à  savoir si ça te dérange ou pas.
  • NoNo Membre
    13:59 modifié #16
    dans 1223975871:

    On peut toujours essayer de forcer l'indexation d'un fichier par la commande mdimport, mais est ce que cela va fonctionner à  l'intérieur d'un .app ?


    Un rapide test sous 10.4 montre clairement que mdimport est incapable d'indexer des fichiers à  l'intérieur d'un bundle .app, même en fournissant un path absolu à  la commande.

    Donc, faut abandonner spotlight pour les recherches intra bundle.

    Reste les solutions :
    - faire son propre outil de recherche (mais dans ce cas faudrait nous expliquer à  quoi servent tes html dans le .app, et surtout pourquoi as-tu besoin d'y faire des recherches textuelles).
    - transférer lesdits html vers un endroit scanné par spotlight (dans ce cas, /Library/Application Support/ est parfait : propre à  l'appli, et reconnu par spotlight, mais avec les limitations -ou failles ?- relevées par Aligator sur le fait que l'interrogation ne sera pas spécifique à  ton appli, mais à  tous les utilisateurs ayant les droits suffisants).
  • Paisible.frPaisible.fr Membre
    13:59 modifié #17
    dans 1224022637:

    dans 1223975871:

    On peut toujours essayer de forcer l'indexation d'un fichier par la commande mdimport, mais est ce que cela va fonctionner à  l'intérieur d'un .app ?

    Un rapide test sous 10.4 montre clairement que mdimport est incapable d'indexer des fichiers à  l'intérieur d'un bundle .app, même en fournissant un path absolu à  la commande.

    Donc, faut abandonner spotlight pour les recherches intra bundle.


    Le même test rapide chez moi (mais sous 10.5) confirme cette conclusion.
    De plus mes recherches sur le net semble corroborrer le tout.
    Donc exit la recherche spotlight intra-bundle !

    dans 1224022637:

    Reste les solutions :
    - faire son propre outil de recherche (mais dans ce cas faudrait nous expliquer à  quoi servent tes html dans le .app, et surtout pourquoi as-tu besoin d'y faire des recherches textuelles).
    - transférer lesdits html vers un endroit scanné par spotlight (dans ce cas, /Library/Application Support/ est parfait : propre à  l'appli, et reconnu par spotlight, mais avec les limitations -ou failles ?- relevées par Aligator sur le fait que l'interrogation ne sera pas spécifique à  ton appli, mais à  tous les utilisateurs ayant les droits suffisants).


    - La solution de faire un MDImporter ne changera rien au fait de pouvoir acceder au contenu intra-bundle je pense. Et puis quel dommage de recoder la même chose que le decodeur SpotLight pour l'HTML d'Appple.

    - La solution de transférer les HTML dans le dossier /Library/Application Support/ (par exemple) me plaà®t moyennement car, d'une part il faut copier les fichiers au départ et c'est un peu dommage d'avoir deux fois le meme contenu de stocker. D'autre part, comme le mentionne Aligator, je ne pense pas que ce soit souhaitable de le voir en dehors de l'application. Meme si c'est pas bloquant en soit.

    - Reste la solution de réaliser son propre outil de recherche. Actuellement je sais parfaitement faire une recherche sur un texte dans un fichier HTML affiché dans une webView. Donc, si j'arrive a effectuer la meme chose directement sur le fichier (sans passer par la webview) et itérant sur les fichiers du dossier je devrais pouvoir m'en tirer. Au pire, si je n'arrive pas à  me passer de la weview, je peux toujours passer par une webView invisible.

    - Enfin, une voie que je n'est pas encore explorée serait de passer par le SearchKit.
  • NoNo Membre
    octobre 2008 modifié #18
    Si tes fichiers html sont des fichiers d'aide (ou que l'on peut considéré comme tel, par exemple de la doc), tu peux utiliser l'api de l'aide Apple.
    Par contre, les fichiers html doivent avoir un certain formatage (c'est à  dire des balises spécifiques dans le html) afin que la recherche soit possible.
    Cette API est disponible sous cocoa via la classe NSHelpManager.
  • Paisible.frPaisible.fr Membre
    13:59 modifié #19
    dans 1224063291:

    Si tes fichiers html sont des fichiers d'aide (ou que l'on peut considéré comme tel, par exemple de la doc), tu peux utiliser l'api de l'aide Apple.
    Par contre, les fichiers html doivent avoir un certain formatage (c'est à  dire des balises spécifiques dans le html) afin que la recherche soit possible.
    Cette API est disponible sous cocoa via la classe NSHelpManager.

    Bonne idée No, mais dans mon cas cela ne va pas convenir.
    Merci quand même.

    Je pense creuser la piste du WebKit...
Connectez-vous ou Inscrivez-vous pour répondre.