Warning, /multimedia/amarok/HACKING/intro_and_style.txt is written in an unsupported language. File is not indexed.

0001 Hacking on Amarok
0002 -----------------
0003 
0004 Have a look at the community wiki for further information.
0005 Also have a look at the requirements for Amarok here:
0006 http://community.kde.org/Amarok/Development/Requirements
0007 
0008 Join the irc channel.
0009 
0010 New requirements, bugfixes and every other patch goes to the
0011 review board.
0012 Try not to post patches in the bugs database or the mailing list.
0013 
0014 Please respect these guidelines when coding for Amarok, thanks!
0015 
0016 * Where this document isn't clear, refer to Amarok code.
0017 
0018 
0019 This C++ FAQ is a life saver in many situations, so you want to keep it handy:
0020 
0021   http://www.parashift.com/c++-faq-lite/
0022 
0023 
0024 Formatting
0025 ----------
0026 * Spaces, not tabs
0027 * Indentation is 4 spaces
0028 * Lines should be limited to 90 characters
0029 * Spaces between brackets and argument functions, except for template arguments
0030 * For pointer and reference variable declarations put a space between the type
0031   and the * or & and no space before the variable name.
0032 * For if, else, while and similar statements put the brackets on the next line,
0033   although brackets are not needed for single statements.
0034 * Function and class definitions have their brackets on separate lines
0035 * A function implementation's return type is on its own line.
0036 * CamelCase.{cpp,h} style file names.
0037 * Qt includes a foreach keyword which makes it very easy to iterate over all
0038   elements of a container.
0039 
0040 Example:
0041 
0042  | bool
0043  | MyClass::myMethod( QStringList list, const QString &name )
0044  | {
0045  |     if( list.isEmpty() )
0046  |         return false;
0047  |
0048  |     /* Define the temporary variable like this to restrict its scope
0049  |      * when you do not need it outside the loop. Let the compiler
0050  |      * optimise it. */
0051  |     foreach( const QString &string, list )
0052  |         debug() << "Current string is " << string << Qt::endl;
0053  |
0054  |     switch( m_enumValue )
0055  |     {
0056  |         case Something:
0057  |             return true;
0058  |         case SomethingElse:
0059  |         {
0060  |             int auxiliaryVariable; // needs scoping in case construct
0061  |             break;
0062  |         }
0063  |     }
0064  | }
0065 
0066 
0067 Using "astyle" for auto formatting
0068 ----------------------------------
0069 The program astyle can be used to automatically format source code, which can
0070 be useful for badly formatted 3rd party patches.
0071 
0072 Use it like this to get (approximately) Amarok formatting style:
0073 
0074     "astyle -s4 -b -p -U -D -o source.cpp"
0075 
0076 
0077 Class, Function & Variable Naming
0078 ---------------------------------
0079 *Use CamelCase for everything.
0080 *Local variables should start out with a lowercase letter.
0081 *Class names are captialized
0082 *Prefix class member variables with m_, ex. m_trackList.
0083 *Prefix static member variables with s_, ex s_instance
0084 *Functions are named in the Qt style. It's like Java's, without the "get" 
0085  prefix.
0086   *A getter is variable()
0087   *If it's a getter for a boolean, prefix with 'is', so isCondition()
0088   *A setter is setVariable( arg ).
0089 
0090 
0091 Includes
0092 --------
0093 Header includes should be listed in the following order:
0094     - Own Header
0095     - Amarok includes, relative to src/ (or shared/) preferably
0096     - KDE includes, <KJob> is preferred to <kjob.h>
0097     - Qt includes
0098     - other includes
0099 
0100 They should also be sorted alphabetically (case-sensitively: classes on same level before
0101 folders), for ease of locating them. A small comment if applicable is also helpful.
0102 
0103 Includes in a header file should be kept to the absolute minimum, as to keep compile times
0104 low. This can be achieved by using "forward declarations" instead of includes, like
0105 "class QListView;"
0106 
0107 TIP:
0108 Kate/KDevelop users can sort the headers automatically. Select the lines you want to sort,
0109 then Tools -> Filter Selection Through Command -> "sort".
0110 
0111 In vim the same can be achieved by marking the block, and then doing ":sort".
0112 
0113 Example:
0114 
0115  | #include "MySuperWidget.h"
0116  |
0117  | #include "EngineController.h"
0118  | #include "core/playlists/Playlist.h"
0119  | #include "core/support/Debug.h"
0120  | #include "core/support/Amarok.h"
0121  |
0122  | #include <KDialogBase> // baseclass
0123  | #include <KPushButton> // see function...
0124  |
0125  | #include <QGraphicsView>
0126  | #include <QWidget>
0127 
0128 
0129 Comments
0130 --------
0131 Comment your code. Don't comment what the code does, comment on the purpose of the code. It's
0132 good for others reading your code, and ultimately it's good for you too.
0133 
0134 Comments are essential when adding a strange hack, like the following example:
0135 
0136  | /**
0137  |  * Due to xine-lib, we have to make K3Process close all fds, otherwise we get "device
0138  |  * is busy" messages. Used by AmarokProcIO and AmarokProcess, exploiting commSetupDoneC(),
0139  |  * a virtual method that happens to be called in the forked process.
0140  |  * See bug #103750 for more information.
0141  |  */
0142  | class AmarokProcIO : public K3ProcIO 
0143  | {
0144  |     public:
0145  |         virtual int commSetupDoneC();
0146  | };
0147 
0148 
0149 Otherwise the comment is in the header. Use the Doxygen syntax. See: http://www.stack.nl/~dimitri/doxygen/
0150 You should be able to write this comment and explain the what the function does.
0151 If you can't, go back to the code and think what you really wanted to do.
0152 If the comment is getting to complicated or confusing, go back to the code and do better.
0153 
0154 Example:
0155 
0156  | /**
0157  |  * Start playback.
0158  |  * @param offset Start playing at @p msec position.
0159  |  * @return True for success.
0160  |  */
0161  | virtual bool play( uint offset = 0 ) = 0;
0162 
0163 
0164 Header Formatting
0165 -----------------
0166 General rules apply here.  Please keep header function definitions aligned nicely,
0167 if possible.  It helps greatly when looking through the code.  Sorted methods,
0168 either by name or by their function (ie, group all related methods together) is
0169 great too. Access levels should be sorted in this order: public, protected, private.
0170 
0171  | #ifndef AMAROK_QUEUEMANAGER_H
0172  | #define AMAROK_QUEUEMANAGER_H
0173  |
0174  | #include <QListView>
0175  |
0176  | namespace MyNamespace {
0177  |     /**
0178  |      * View showing currently queued tracks.
0179  |      */
0180  |     class QueueList : public QListView
0181  |     {
0182  |         Q_OBJECT
0183  |
0184  |         public:
0185  |             explicit QueueList( QWidget *parent, const QString ̛&name = QString() );
0186  |             ~QueueList();
0187  |
0188  |         public slots:
0189  |             void moveSelectedUp();
0190  |             void moveSelectedDown();
0191  |
0192  |         private:
0193  |             int m_member;
0194  |             QHash<int, QString> m_names;
0195  |     };
0196  | } // namespace MyNamespace
0197  |
0198  | #endif /* AMAROK_QUEUEMANAGER_H */
0199 
0200 
0201 Associated .cpp file could look like (skipping license):
0202 
0203  | #define DEBUG_PREFIX "MyNamespace::QueueList" // only if you use debug(), warning()...
0204  |
0205  | #include "QueueList.h"
0206  |
0207  | using namespace MyNamespace;
0208  |
0209  | QueueList::QueueList( QWidget *parent, const QString ̛&name )
0210  |     : QListView( parent )
0211  |     , m_member( name.length() )
0212  | {
0213  | }
0214 
0215 
0216 0 vs NULL
0217 ---------
0218 The use of 0 to express a null pointer is preferred over the use of NULL.
0219 0 is not a magic value, it's the defined value of the null pointer in C++.
0220 NULL, on the other hand, is a preprocessor directive (#define) and not only is
0221 it more typing than '0' but preprocessor directives are less elegant.
0222 
0223  |     SomeClass *instance = 0;
0224 
0225 
0226 Const Correctness
0227 -----------------
0228 Try to keep your code const correct. Declare methods const if they don't mutate the object,
0229 and use const variables. It improves safety, and also makes it easier to understand the code.
0230 
0231 See: http://www.parashift.com/c++-faq-lite/const-correctness.html
0232      const_correstness.txt
0233 
0234 Example:
0235 
0236  | bool
0237  | MyClass::isValidFile( const QString &path ) const
0238  | {
0239  |     const bool valid = QFile::exist( path );
0240  |     return valid;
0241  | }
0242 
0243 
0244 Debugging
0245 ---------
0246 debug.h contains some handy functions for our debug console output.
0247 Please use them instead of kDebug().
0248 
0249 Usage:
0250 
0251  | #include "debug.h"
0252  |
0253  | debug() << "Something is happening";
0254  | warning() << "Something bad may happen";
0255  | error() << "Something bad did happen!";
0256 
0257 Additionally, there are some macros for debugging functions:
0258 
0259 DEBUG_BLOCK
0260 DEBUG_FUNC_INFO
0261 DEBUG_LINE_INFO
0262 DEBUG_INDENT
0263 DEBUG_UNINDENT
0264 
0265 AMAROK_NOTIMPLEMENTED
0266 AMAROK_DEPRECATED
0267 
0268 threadweaver.h has two additional macros:
0269 DEBUG_THREAD_FUNC_INFO outputs the memory address of the current QThread or 'none'
0270     if its the original GUI thread.
0271 SHOULD_BE_GUI outputs a warning message if it occurs in a thread that isn't in
0272     the original "GUI Thread", otherwise it is silent. Useful for documenting
0273     functions and to prevent problems in the future.
0274 
0275 
0276 Errors & Asserts
0277 ----------------
0278 *Use Q_ASSERT where appropriate. If you don't know what an assert is, look it up now.
0279 
0280 *Never use fatal(). There must be a better option than crashing a user's
0281 application (its not uncommon for end-users to have debugging enabled).
0282 
0283 *KMessageBox is fine to use to prompt the user, but do not use it to display errors
0284 or informational messages. Instead, KDE::StatusBar has a few handy methods. Refer to
0285 amarok/src/statusbar/statusBarBase.h
0286 
0287 
0288 Commenting Out Code
0289 -------------------
0290 Don't keep commented out code. It just causes confusion and makes the source
0291 harder to read. Remember, the last revision before your change is always
0292 availabe in Git. Hence no need for leaving cruft in the source.
0293 
0294 Wrong:
0295  | myWidget->show();
0296  | //myWidget->rise(); // what is this good for?
0297 
0298 Correct:
0299  | myWidget->show();
0300 
0301 
0302 Unit Tests and API Docs
0303 -----------------------
0304 Amarok uses the "Jenkins" system for doing automatic nightly builds, checking for
0305 compile errors, and visualizing Unit Tests. You can see the results here:
0306 
0307 http://build.kde.org/view/EXTRAGEAR/job/amarok_master/
0308 
0309 The API DOc for Amarok can be found here:
0310 
0311 http://api.kde.org/extragear-api/multimedia-apidocs/amarok/html/index.html
0312 
0313 
0314 Tips & Tricks
0315 -------------
0316 A useful service is http://lxr.kde.org. Lxr is a cross reference of the entire
0317 KDE SVN repository. You can for instance use it to search for example code
0318 from other applications for a given KDElibs method.
0319 
0320 
0321 Markey's .vimrc
0322 ---------------
0323 
0324 let ruby_no_expensive = 1
0325 syntax on
0326 
0327 set shiftwidth=4
0328 set tabstop=4
0329 set expandtab
0330 set hlsearch
0331 set ruler
0332 set smartindent
0333 set nowrap
0334 
0335 set ignorecase
0336 set smartcase
0337 
0338 set title
0339 set showtabline=2  "Makes the status bar always show, also for just one tab
0340 
0341 autocmd FileType ruby set shiftwidth=2 tabstop=2
0342 
0343 
0344 Git and SVN aware prompt
0345 ----------------
0346 The following prompt shows the current git branch if sitting in a git repository.
0347 Random crap courtesy of shell colours.
0348 export PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\[\033[01;33m\]`git branch 2>/dev/null|cut -f2 -d\* -s`\[\033[00m\]\$ '
0349 
0350 This is an even more colorful configuration for .bashrc that displays the
0351 current git branch if sitting in a git repository and the current SVN revision
0352 if sitting in an SVN checkout.
0353 svn_prompt() {
0354         SVNBRANCH=`svn info 2>/dev/null | grep Revision: | cut -f 2 -d " "`
0355         if [ -n "$SVNBRANCH" ]; then
0356                 BRANCH=" (r$SVNBRANCH)";
0357         else
0358                 BRANCH="";
0359         fi
0360     echo "$BRANCH"
0361 }
0362 export PS1='\[\e[0;32m\]\u@\h\[\e[m\] \[\e[1;34m\]\w\[\e[m\]\[\033[01;33m\]`__git_ps1`\[\e[m\]\[\e[01;35m\]`svn_prompt`\[\e[m\]\[\033[00m\]  \[\e[1;32m\]\$ \[\e[m\]\[\e[1;37m\] '
0363 
0364 Git KDE commit template
0365 -----------------------
0366 
0367 HACKING/commit-template should be used so commits to KDE git servers are properly formatted and using the commit keywords.
0368 configure git to use the template using:
0369 git config commit.template HACKING/commmit-template
0370 
0371 Copyright
0372 ---------
0373 To comply with the GPL, add your name, email address & the year to the top of any file
0374 that you edit. If you bring in code or files from elsewhere, make sure its
0375 GPL-compatible and to put the authors name, email & copyright year to the top of
0376 those files.
0377 
0378 Please note that it is not sufficient to write a pointer to the license (like a URL).
0379 The complete license header needs to be written everytime.
0380 
0381 
0382 Thanks, now have fun!
0383   -- the Amarok developers