Viktigt

Översättning är en gemenskapsinsats du kan gå med i. Den här sidan är för närvarande översatt till 100.00%.

1. QGIS kodningsstandarder

QGIS kodningsstandarder beskrivs i policydokumentet som finns tillgängligt på QEP #314. Alla utvecklare är skyldiga att följa dessa policyer. Observera att QEP #314 är ett aktuellt dokument och att dessa policyer kan komma att ändras över tid.

1.1. Klasser

1.1.1. Accessorfunktioner

Se till att accessorer är korrekt markerade med const. I förekommande fall kan detta kräva att medlemsvariabler av typen cached value markeras med mutable.

1.1.2. Funktion Arguments

Var noga med när argument ska skickas med referens. Om inte argumentobjekten är små och trivialt kopierade (t.ex. QPoint-objekt) bör de skickas med const-referens. För att vara konsekvent med Qt API, skickas även implicit delade objekt med const-referens (t.ex. setTitle( const QString& title ) istället för setTitle( QString title ).

1.1.3. Funktion Returvärden

Returnera små och trivialt kopierade objekt som värden. Större objekt bör returneras med const-referens. Det enda undantaget från detta är implicit delade objekt, som alltid returneras som värde. Returnera QObject eller underklassade objekt som pekare.

  • int maximumValue() const

  • const LayerSet& layers() const

  • QString title() const (QString är implicit delad)

  • QList< QgsMapLayer* > layers() const (QList är implicit delad)

  • QgsVectorLayer *layer() const; (QgsVectorLayer ärver QObject)

  • QgsAbstractGeometry *geometry() const; (QgsAbstractGeometry är abstrakt och kommer förmodligen att behöva castas)

1.2. API-dokumentation

Det är obligatoriskt att skriva API-dokumentation för varje klass, metod, enum och annan kod som finns tillgänglig i det publika API:et.

QGIS använder Doxygen för dokumentation. Skriv beskrivande och meningsfulla kommentarer som ger läsaren information om vad han eller hon kan förvänta sig, vad som händer i undantagsfall och ger tips om andra gränssnitt som han eller hon kan leta efter, bästa praxis och kodexempel.

1.2.1. Medlemmar Variabler

Medlemsvariabler ska normalt ligga i avsnittet private och göras tillgängliga via getters och setters. Ett undantag från detta är för datacontainrar som för felrapportering. I sådana fall ska man inte prefixera medlemmen med ett m.

1.3. Qt Designer

1.3.1. Genererade klasser

QGIS-klasser som genereras från Qt Designer (ui)-filer bör ha ett Base-suffix. Detta identifierar klassen som en genererad basklass.

Exempel:

  • QgsPluginManagerBase

  • QgsUserOptionsBase

1.3.2. Dialoger

Alla dialogrutor bör implementera verktygstips för alla ikoner i verktygsfältet och andra relevanta widgets. Verktygstips gör det mycket lättare för både nya och erfarna användare att hitta funktioner.

Se till att flikordningen för widgetar uppdateras när layouten för en dialog ändras.

1.4. C++-filer

1.4.1. Standardhuvud och licens

Varje källfil ska innehålla ett huvudavsnitt enligt följande exempel:

/***************************************************************************
  qgsfield.cpp - Describes a field in a layer or table
  --------------------------------------
  Date : 01-Jan-2004
  Copyright: (C) 2004 by Gary E.Sherman
  Email: sherman at mrcc.com
/***************************************************************************
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 ***************************************************************************/

Observera

Det finns en mall för Qt Creator i git-repository. För att använda den, kopiera den från qt_creator_license_template till en lokal plats, justera e-postadressen och - om så krävs - namnet och konfigurera QtCreator att använda den: Tools ► Options ► C++ ► File Naming.

1.5. Ändrar

Alla textredigerare/IDE kan användas för att redigera QGIS-kod, förutsatt att följande krav är uppfyllda.

1.5.1. Tabulatorer

Ställ in din editor så att den emulerar tabbar med mellanslag. Tabbavstånd bör ställas in på 2 mellanslag.

Observera

I vim görs detta med set expandtab ts=2

1.5.2. Indrag

Källkod bör vara indragen för att förbättra läsbarheten. Det finns en prepare_commit.sh-fil som letar upp de ändrade filerna och indenterar dem på nytt med hjälp av astyle. Detta bör köras innan du skickar. Du kan också använda astyle.sh för att indentera enskilda filer.

Eftersom nyare versioner av astyle indenterar på ett annat sätt än den version som används för att göra en fullständig omindentering av källan, använder skriptet en gammal astyle-version som vi inkluderar i vårt arkiv (aktivera WITH_ASTYLE i cmake för att inkludera den i byggandet).

1.6. API-kompatibilitet

Det finns API-dokumentation för C++.

Vi försöker hålla API:et stabilt och bakåtkompatibelt. Uppstädningar av API:et bör göras på ett sätt som liknar Qt-källkoden, t.ex.

class Foo
{
  public:
    /**
     * This method will be deprecated, you are encouraged to use
     * doSomethingBetter() rather.
     * \deprecated use doSomethingBetter()
     */
    Q_DECL_DEPRECATED bool doSomething();

    /**
     * Does something a better way.
     * \note added in 1.1
     */
    bool doSomethingBetter();

  signals:
    /**
     * This signal will be deprecated, you are encouraged to
     * connect to somethingHappenedBetter() rather.
     * \deprecated use somethingHappenedBetter()
     */
#ifndef Q_MOC_RUN
    Q_DECL_DEPRECATED
#endif
    bool somethingHappened();

    /**
     * Something happened
     * \note added in 1.1
     */
    bool somethingHappenedBetter();
}

1.7. SIP-bindningar

Vissa av SIP-filerna genereras automatiskt med hjälp av ett särskilt skript.

1.7.1. Förbehandling av rubriker

All information för att bygga SIP-filen på rätt sätt måste finnas i C++-headerfilen. Vissa makron finns tillgängliga för sådan definition:

  • Använd #ifdef SIP_RUN för att generera kod endast i SIP-filer eller #ifndef SIP_RUN för C++-kod endast. #else-satser hanteras i båda fallen.

  • Använd SIP_SKIP för att förkasta en rad

  • Följande anteckningar hanteras:

    • SIP_FACTORY: /Factory/

    • SIP_OUT: /Out/

    • SIP_INOUT: /In,Out/

    • SIP_TRANSFER: /Transfer/

    • SIP_PYNAME(name): /PyName=name/

    • SIP_KEEPREFERENCE: /KeepReference/

    • SIP_TRANSFERTHIS: /TransferThis/

    • SIP_TRANSFERBACK: /TransferBack/

  • privata sektioner visas inte, förutom om du använder en #ifdef SIP_RUN-sats i detta block.

  • SIP_PYDEFAULTVALUE(value) kan användas för att definiera ett alternativt standardvärde för pythonmetoden. Om standardvärdet innehåller ett kommatecken ,, ska värdet omges av enkla citattecken '

  • SIP_PYTYPE(type) kan användas för att definiera en alternativ typ för ett argument i pythonmetoden. Om typen innehåller ett kommatecken ,, ska typen omges av enkla citattecken '

En demofil, sipifyheader.h, finns också tillgänglig.

1.7.2. Generering av SIP-filen

SIP-filen kan genereras med hjälp av ett särskilt skript. Till exempel:

scripts/sipify.pl src/core/qgsvectorlayer.h > python/core/qgsvectorlayer.sip

För att automatiskt generera SIP-filen för en nyligen tillagd C++-fil måste sip_include.sh köras.

Så snart en SIP-fil läggs till i en av källfilerna (core_auto.sip, gui_auto.sip eller analysis_auto.sip) kommer den att betraktas som automatiskt genererad. Ett test kommer att säkerställa att filen är uppdaterad med motsvarande header.

För att tvinga fram återskapande av SIP-filer ska sipify_all.sh köras.

1.7.3. Förbättring av sipify-skriptet

Om några förbättringar krävs för sipify-skriptet, lägg till de saknade bitarna i demofilen sipifyheader.h och skapa den förväntade rubriken sipifyheader.expected.sip-filen. Detta kommer också att testas automatiskt som ett enhetstest av själva skriptet.

1.8. Inställningar

QGIS kodbas erbjuder en mekanism för att deklarera, registrera och använda inställningar.

  • inställningar bör definieras med hjälp av en av de tillgängliga implementationerna (QgsSettingsEntryString, QgsSettingsEntryInteger, …).

  • inställningar måste integreras i inställningsträdet (QgsSettingsTree), detta görs automatiskt när man använder konstruktorn med en överordnad nod (QgsSettingsTreeNode).

  • de deklareras som const static antingen i en särskild klass eller direkt i registret (core, gui, app, …).

  • inställningsnyckeln bör använda ett kebab-fodral.

1.9. Kodningsstil

Här beskrivs några programmeringstips som förhoppningsvis kommer att minska fel, utvecklingstid och underhåll.

1.9.1. Generalisera koden där det är möjligt

Om du klipper och klistrar kod eller på annat sätt skriver samma sak mer än en gång kan du överväga att konsolidera koden till en enda funktion.

Det kommer det att göra:

  • göra det möjligt att göra ändringar på en plats i stället för på flera platser

  • hjälpa till att förhindra uppsvälld kod

  • göra det svårare för flera kopior att utveckla skillnader över tiden, vilket gör det svårare att förstå och underhålla för andra

1.9.2. Skriv kommandon på separata rader

När man läser kod är det lätt att missa kommandon om de inte står i början av raden. När man snabbt läser igenom kod är det vanligt att hoppa över rader om de inte ser ut som det man letar efter i de första tecknen. Det är också vanligt att man förväntar sig ett kommando efter ett villkor som if.

Tänk på det:

if (foo) bar();

baz(); bar();

Det är mycket lätt att missa en del av vad kontrollflödet. Använd istället

if (foo)
  bar();

baz();
bar();

1.9.3. Bokrekommendationer

Du bör också verkligen läsa den här artikeln från Qt Quarterly om designing Qt style (APIs)

1.10. Tillgodoräknande av bidrag

De som bidrar med nya funktioner uppmanas att informera andra om sitt bidrag genom att göra detta: