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