1 /***************************************************************************
2 * KMK - KDE Music Cataloger - the tool for personal *
3 * audio collection management *
5 * Copyright (C) 2006,2007 by Plamen Petrov *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
32 #include <kmainwindow.h>
34 //#include <kfiledialog.h>
36 #include <klistview.h>
37 #include <klineedit.h>
39 //#include <qvaluelist.h>
43 #include <qsplitter.h>
45 #include <qdatetime.h>
46 #include <qdragobject.h>
48 #include "kmk_progress_disp.h"
50 #include "kmkglobalsettings.h"
51 #include "kmkexternalplayer.h"
67 class kmk_progress_disp
;
69 class kmk_tree_KListView
: public KListView
73 kmk_tree_KListView (QWidget
*parent
= 0, const char *name
= 0)
74 : KListView ( parent
, name
)
76 virtual ~kmk_tree_KListView()
79 virtual QDragObject
*dragObject()
81 QListViewItem
* lv
= this->currentItem();
87 p
.prepend( lv
->text(0) );
88 if( lv
->parent() ) { p
.prepend( "/" ); lv
= lv
->parent(); }
94 QUriDrag
*d
= new QUriDrag( this, 0 );
97 return (QDragObject
*) d
;
101 class kmk_files_KListView
: public KListView
105 kmk_files_KListView (QWidget
*parent
= 0, const char *name
= 0)
106 : KListView ( parent
, name
)
108 virtual ~kmk_files_KListView()
111 virtual QDragObject
*dragObject()
114 KListViewItem
*node
= (KListViewItem
*) this->firstChild();
115 if ( !node
) return 0;
119 if ( node
->isSelected() ) l
<< node
->text( 0 ) + "/" + node
->text( 1 );
120 node
= (KListViewItem
*) node
->nextSibling();
123 QUriDrag
*d
= new QUriDrag( this, 0 );
125 d
->setFileNames( l
);
126 return (QDragObject
*) d
;
131 * @short kmk is the main widget which actually makes KMK what it is
133 * This Widget extends the functionality of QListView to honor the system
134 * wide settings for Single Click/Double Click mode, AutoSelection and
135 * ChangeCursorOverLink (TM).
137 * There is a new signal executed(). It gets connected to either
138 * QListView::clicked() or QListView::doubleClicked() depending on the KDE
139 * wide Single Click/Double Click settings. It is strongly recommended that
140 * you use this signal instead of the above mentioned. This way you don�t
141 * need to care about the current settings.
142 * If you want to get informed when the user selects something connect to the
143 * QListView::selectionChanged() signal.
145 * Drag-and-Drop is supported with the signal dropped(), just setAcceptDrops(true)
146 * and connect it to a suitable slot.
147 * To see where you are dropping, setDropVisualizer(true).
148 * And also you'll need acceptDrag(QDropEvent*)
150 * KListView is drag-enabled, too: to benefit from that you have to derive from it.
151 * Reimplement dragObject() and (possibly) startDrag(),
152 * and setDragEnabled(true).
154 * @author Plamen Petrov <carpo@abv.bg>
157 class kmk
: public KMainWindow
162 * Default constructor
174 * Handle searching trough the selected dir - scan for files
175 * we recognize, and add them accordingly to the catalog tree;
176 * This SLOT initially cleans all contents of MusicCatalog,
177 * the Catalog tree KListView, and the two File list QTables
181 void slotCatalogAddNewFolder();
182 /** Saves the catalog in memory to the file @p catalogFileName;
183 * If the string, being a filename in @p catalogFileName does not have
184 * a .kmk extension - this slot adds it
187 void slotFileSaveAs();
188 void slotCatalogFileClose();
189 void slotCatalogFileStats();
192 void slotProgramSettings();
195 * This is where the setup for kmkTagEdit takes place:
196 * a QTable::selection(s) is traversersed and relevant data
197 * extracted in MmDataList, for user manipulation in the TagEditor
201 void slotListTableToggleTitle();
204 * A private slot for kmk which takes care of making the external player
205 * play the previous song - either the song before the current in its
206 * playlist, or if it is in SHUFFLE mode - the previous played
208 void slotPlayerPrevious();
211 * A private slot for kmk which takes care of making the external player
212 * play; if it was playing something at the time the command is issued
213 * there should be no effect whatsoever
215 void slotPlayerPlay();
218 * A private slot for kmk which makes the external player
219 * pause - in reality - if it was paused, it will continue;
220 * if it was playing - it will pause
222 void slotPlayerPause();
225 * A private slot for kmk which makes the external player stop
226 * playing if it is; if it isn't - there is no effect
228 void slotPlayerStop();
231 * Private kmk slot, which essentially behaves like kmk::playerPrevious()
232 * only difference is the "direction"
234 void slotPlayerNext();
237 * This private kmk slot is resposible for enqueing whatever is selected
238 * in the FileList() QTables, or SearchFileList() QTable - its native
239 * call environment is from a popup menu after recieved
240 * contextMenuRequested() signal
242 void slotPlayerEnqueue();
245 * Uses kmk::playerDir to enqueue
247 void slotPlayerEnqueueDir();
250 * Uses kmk::playerDir to enqueue selected folder AND all its subfolder(s) contents
252 void slotPlayerEnqueueDirSubdirs();
255 * Uses kmk::playerDir to play
257 void slotPlayerPlayDir();
260 * Uses kmk::playerDir to play selected folder AND all its subfolder(s) contents
262 void slotPlayerPlayDirSubdirs();
265 * This private slot should play whatever selection in FileList()
266 * or kmkWidget::SearchTreeList() QTable objects
268 void slotPlayerPlaySelection();
271 * Triggers update on currently selected folder in TreeListView
273 void slotCatalogUpdateSubtree();
275 void slotTreeListViewPopupMenuRequested( QListViewItem
* itm
, const QPoint
&pos
, int col
);
276 void slotTreeListViewCurrentChanged( QListViewItem
* itm
);
278 void slotFileListTablePopupMenuRequested( QListViewItem
* itm
, const QPoint
&pos
, int col
);
279 void slotSearchListTablePopupMenuRequested( QListViewItem
* itm
, const QPoint
&pos
, int col
);
282 * Available for selection in the search results table popup menu ONLY when
283 * one item (row) is selected; shows the catalag AND selects the folder
284 * containing the selected item (currently only files are listed).
286 void slotLocateRequested();
288 void slotSearchButtonClicked();
289 void slotClearButtonClicked();
290 void slotDoneButtonClicked();
292 void slotUpdateProgressDisp();
296 QWidget
* main_container_widget
;
297 QTabWidget
* tabWidget1
;
299 QSplitter
* splitter1
;
300 kmk_tree_KListView
* treeListView
;
301 kmk_files_KListView
* filesListView
;
302 kmk_files_KListView
* searchFilesListView
;
304 QTabWidget
* tabWidget2
;
306 QPushButton
* pbSearch
;
307 QPushButton
* pbClear
;
311 KLineEdit
* leSearchFor
;
314 KToolBar
* fileToolsToolbar
;
315 KToolBar
* playerActionsToolbar
;
316 KAction
* fileNewAction
;
317 KAction
* fileOpenAction
;
318 KAction
* catalogAddNewFolderAction
;
319 KAction
* fileSaveAction
;
320 KAction
* fileSaveAsAction
;
321 KAction
* fileCatalogFileClose
;
322 KAction
* fileCatalogFileStats
;
323 KAction
* fileQuitAction
;
324 KAction
* programSettingsAction
;
325 KAction
* listTableToggleTitleAction
;
326 KAction
* TagEditAction
;
327 KAction
* listTableLocateAction
;
328 KAction
* playerPreviousAction
;
329 KAction
* playerPlayAction
;
330 KAction
* playerPauseAction
;
331 KAction
* playerStopAction
;
332 KAction
* playerNextAction
;
333 KAction
* playerEnqueueAction
;
334 KAction
* playerEnqueueDirAction
;
335 KAction
* playerEnqueueDirSubdirsAction
;
336 KAction
* playerPlayDirAction
;
337 KAction
* playerPlayDirSubdirsAction
;
338 KAction
* playerPlaySelectionAction
;
339 KAction
* catalogUpdateSubtreeAction
;
341 QPopupMenu
* CTree_PopupMenu
;
342 QPopupMenu
* CList_PopupMenu
;
343 QPopupMenu
* CSearchList_PopupMenu
;
345 void init_interface();
347 // kmkWidget* kmk_widg;
348 KListViewItem
* cur_vlItem
;
349 KListViewItem
* listViewRootItem
;
350 MmDataList MusicCatalog
;
352 enum CatalogStateEnum
{
358 CatalogStateEnum CatalogState
;
359 void setCatalogStateAndUpdate( const kmk::CatalogStateEnum state
);
362 * locateMode [bool] if set to TRUE indicates to the
363 * treeListViewCurrentChanged method that it should select
364 * the row, containing DelSelFile AND DelSelDir, if it finds them
365 * during the FileList() table update...
371 void clearCatalogData( const bool UpdateState
= TRUE
);
374 * Used to indicate whether we should stop a long disk operation:
375 * scanning, updating, etc; checked were appropriate:
376 * in traverse_tree( const QString& dir ); and bytes_to_read_by_traverse( const QString& dir );
378 bool break_long_disk_operation
;
379 kmk_progress_disp
* kmkProgress
;
380 QTimer
* kmkProgressTimer
;
383 bool FileSaveCalledFromFileSaveAs
;
385 /** Finds all files in kmkWidget::TreeList() currentItem and all its subfolders
386 * and passes them to player_bin with parameter @param act
388 void playerDir( uint act
);
391 * This private function implements recursive search at the
392 * top level dir, specified in the @p dir parameter;
393 * currently there are absolutely no checks if the dir is valid -
394 * first, because this function is called from controlled environment;
395 * second, as I described - it is recursive, so we don't want to loose
396 * any speed, checking if we are called with valid input
398 unsigned long traverse_tree( const QString
& dir
, const QString
& pf
= "AUTO" );
401 * Remove a folder inside a MmData list and all of its children
403 * NOTE: @p folder must NOT have the slash / symbol in the end!!!
404 * @return 0 - on succes
407 uint
rem_MmData_Folder( MmDataList
* list
, const QString
& folder
);
410 * This private function starts by clearing current contents of
411 * Tree KListView; next it goes trough kmk's MusicCatalog, recreating
412 * the tree, described in the MmData structure, inside the Tree view
414 void update_tree_view();
415 bool tree_needs_update
;
416 void bytes_to_read_by_traverse( const QString
& dir
);
417 void generateListViewXML( const KListView
*list
, QDomDocument doc
, QDomElement e
);
418 uint
generateListViewSubtreeXML( const KListViewItem
*item
, QDomDocument doc
, QDomElement e
, const uint add_lv
);
419 MmData
* findMmData( const QString
& folder
, const QString
& filename
);
420 void loadCatalog( const QString
& fileName
);
421 unsigned int subDlevel
;
423 * Holds TRUE if Enqueue dir in kmkWidget::FileList() popup
424 * menu should add subdirs, FALSE if not
426 bool _kmk_include_subdirs
;
428 * This boolean variable, local and private for kmk indicates
429 * wether a popup menu, including id3 tag editor submenu
430 * was requested at file list in the catalog tab,
431 * or at the search result file list.
433 bool _popup_at_search
;
434 const QString
formatted_string_from_seconds( const Q_ULLONG t
);
435 const bool catalog_has_dir( const QString
& );
436 void update_catalog_stats( MmDataList
* list
);
437 /** Some stats variables
439 Q_ULLONG bytes_to_read
;
440 Q_ULLONG files_to_read
;
441 Q_ULLONG total_bytes
;
442 Q_ULLONG total_files
;
443 Q_ULLONG total_folders
;
444 Q_ULLONG total_play_time
;
445 Q_ULLONG average_file_size
;
446 QString savedCaption
;
447 QString catalogFileName
;
449 KmkGlobalSettings
* s
;
450 KmkExtPlayer
* player
;
453 void closeEvent( QCloseEvent
* ce
);
455 QVBoxLayout
* kmkwidgetbaseLayout
;
456 QVBoxLayout
* tabLayout
;
457 QVBoxLayout
* tabLayout_2
;
458 QVBoxLayout
* layout5
;