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