<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
@font-face
        {font-family:"Courier New\,courier";
        panose-1:0 0 0 0 0 0 0 0 0 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        color:black;
        mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0cm;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";
        color:black;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:36.0pt;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        color:black;
        mso-fareast-language:EN-US;}
span.EmailStyle18
        {mso-style-type:personal;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:Consolas;
        color:black;
        mso-fareast-language:EN-US;}
span.EmailStyle21
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:#1F497D;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:70.85pt 70.85pt 70.85pt 70.85pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body bgcolor="white" lang="NO-BOK" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">Hi Matthias,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">Wow, cool! Thanks for implementing that so fast!<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">I just tested caching in a global variable. It works like a charm and speeds up the GUI significantly.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">And yes, the completer works fine with autogenerated forms too (I only had to restart QGIS).<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">So all my problems in this regards are solved now.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">The only, minor issue is, that one has to set Settings->Options->Enable Macros to “Always”, or “Only this session” (with “Ask” (the default setting) the startup macro does not load, see:</span><span lang="EN-US">
</span><span lang="EN-US" style="color:#1F497D">http://hub.qgis.org/issues/9523) <o:p>
</o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">For those who are interested and who can`t wait for the next release with Matthias additions (and who like me are absolute Python beginners),<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">here is how it works (quite simple actually once you know how to do it):<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">The openProject() Python marco function (in my case named generate_completer.py, located in the project directory)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">looks like this (completer content could also be loaded from file of course):<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">-----------------------------<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">#!/usr/bin/env python<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">from PyQt4.QtCore import *<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">from qgis.core import *<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">import psycopg2<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">def fetch_citems():<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    <o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    global ci<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    #Fetch data from DB to fill completer<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    conn = psycopg2.connect("dbname='MYDB' user='MYUSER' host='MYHOST' password='MYDB'")<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    cur = conn.cursor()<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    cur.execute("""SELECT scientificname FROM kls.l_artsliste WHERE finnesinorge = 'Ja'""")<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    ci = []<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    for row in cur.fetchall():<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">        ci.append(row[0])<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">-----------------------------<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">It is referenced in the project like this:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    import generate_completer<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    generate_completer.fetch_citems()<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">And the form init function (in my case named completer.py, located in the project directory) looks like this:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">-----------------------------<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">from PyQt4.QtCore import *<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">from PyQt4.QtGui import *<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">import generate_completer<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="NO-NYN" style="color:#1F497D">nameField = None<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="NO-NYN" style="color:#1F497D">myDialog = None<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="NO-NYN" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="NO-NYN" style="color:#1F497D">def formOpen(dialog,layerid,featureid):<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="NO-NYN" style="color:#1F497D">    global myDialog<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="NO-NYN" style="color:#1F497D">    myDialog = dialog<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="NO-NYN" style="color:#1F497D">    global nameField<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="NO-NYN" style="color:#1F497D">    </span><span lang="EN-US" style="color:#1F497D">nameField = dialog.findChild(QLineEdit,"latinn")<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    <o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    #Initiate completer<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    completer = QCompleter()<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    nameField.setCompleter(completer)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    <o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    #Add data to Qt Model / QCompleter<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    model = QStringListModel()<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    model.setStringList(generate_completer.ci)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">    completer.setModel(model)
<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">-----------------------------<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">It is referenced in the Fields tab as: completer.formOpen<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">“latinn” is the name of the attribute column BTW for which the completer is used.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">I guess the global variable “ci” (Python list with Unicode strings) could also be used for data validation (in Nathan`s example)…<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">Thanks for this amazing Software!<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">Kind regards,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D">Stefan<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="color:#1F497D"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span lang="EN-US" style="color:windowtext;mso-fareast-language:NO-BOK">From:</span></b><span lang="EN-US" style="color:windowtext;mso-fareast-language:NO-BOK"> qgis-user-bounces@lists.osgeo.org [mailto:qgis-user-bounces@lists.osgeo.org]
<b>On Behalf Of </b>Matthias Kuhn<br>
<b>Sent:</b> 29. mars 2015 19:56<br>
<b>To:</b> qgis-user@lists.osgeo.org<br>
<b>Subject:</b> Re: [Qgis-user] QCompleter in QGIS form<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal" style="margin-bottom:12.0pt">Hi Stefan,<br>
<br>
I had some spare time on the Sunday evening train. So I have just added this possibility to the ValueRelation widget. You can now choose the option "Use Completer" there.<br>
The query is still run every time the form is opened at the moment. There is actually a caching mechanism for the value relation widget prepared, so it should be possible to make use of that and initialize the cache only once.<br>
But that will have to wait until I have some spare time again or one may speed up the process by funding this or tackling the issue if coding skills are available (for the last option, please get in touch first, there are a couple of different approaches to
 doing this),<br>
<br>
Testing is appreciated.<br>
Matthias<span style="font-size:12.0pt;mso-fareast-language:NO-BOK"><o:p></o:p></span></p>
<div>
<p class="MsoNormal">On 03/28/2015 08:32 PM, Blumentrath, Stefan wrote:<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span lang="EN-US">Dear all,</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">Thanks to Nathan`s excellent example here:</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://nathanw.net/2011/09/05/qgis-tips-custom-feature-forms-with-python-logic/">http://nathanw.net/2011/09/05/qgis-tips-custom-feature-forms-with-python-logic/</a></span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">I managed to implement a simple QCompleter for a LineEdit in my form where the completer items are being fetched from DB (see init function code at the end of my mail).</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">This is very, very promising stuff which comes in quite handy for entering species names (from an official list of (thousands of) species names in my case)!</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">Yet there are two things I am struggling with:</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">1) Would it be possible to use this QCompleter solution to an autogenerated form? The auto generated forms are more than good enough for most of my use-cases. When I tried the Init function on an autogenerated form I
 got “</span><span lang="EN-US" style="font-family:"Courier New,courier",serif">NameError: global name 'TextEdit' is not defined”… Any ideas how to fix that?</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">2) It seems to me that the query - which is used to fill the QCompleter - is executed each time the form is opened. Would it be possible to avoid this, I mean that the query is only run once (e.g. when I open the project)?
 I hoped this could speed up the start of the form (even if the query gets cached in PostgreSQL)…</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">Many thanks in advance for helping.</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">Kind regards,</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">Stefan</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">P.S.: Next thing I will have to do is understand SIGNALS and SLOTS so I can adjust the completer content depending on other data entered in the form (e.g. filter species by kingdom or known occurrence in a country (here
 Norway)) …</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">P.P.S.: My form_init.py looks like this:</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">from PyQt4.QtCore import *</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">from PyQt4.QtGui import *</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">from PyQt4.QtSql import *</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">import psycopg2</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="NO-NYN">nameField = None</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="NO-NYN">myDialog = None</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="NO-NYN"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="NO-NYN">def formOpen(dialog,layerid,featureid):</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="NO-NYN">    global myDialog</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="NO-NYN">    myDialog = dialog</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="NO-NYN">    global nameField</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="NO-NYN">    </span><span lang="EN-US">nameField = dialog.findChild(QLineEdit,"latinsk_navn")</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    #Initiate completer</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    completer = QCompleter()</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    nameField.setCompleter(completer)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    #Fetch data from DB to fill completer</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    conn = psycopg2.connect("dbname='MYDB' user='MYUSERNAME' host='MYHOST' password='MYPASSWD'")</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    cur = conn.cursor()</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    cur.execute("""SELECT scientificname FROM kls.l_artsliste WHERE finnesinorge = 'Ja'""")</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    completition_items = []</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    for row in cur.fetchall():</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">        completition_items.append(row[0])</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">               #Add data to Qt Model / QCompleter</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">               model = QStringListModel()</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    model.setStringList(completition_items)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US">    completer.setModel(model)</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:NO-BOK"><br>
<br>
<br>
<o:p></o:p></span></p>
<pre>_______________________________________________<o:p></o:p></pre>
<pre>Qgis-user mailing list<o:p></o:p></pre>
<pre><a href="mailto:Qgis-user@lists.osgeo.org">Qgis-user@lists.osgeo.org</a><o:p></o:p></pre>
<pre><a href="http://lists.osgeo.org/mailman/listinfo/qgis-user">http://lists.osgeo.org/mailman/listinfo/qgis-user</a><o:p></o:p></pre>
</blockquote>
<p class="MsoNormal"><span style="font-size:12.0pt;font-family:"Times New Roman",serif;mso-fareast-language:NO-BOK"><o:p> </o:p></span></p>
</div>
</body>
</html>