stationlistwidget.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2008-2010  Lukas Sommer < SommerLuk at gmail dot com >
00003 
00004     This program is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU General Public License as
00006     published by the Free Software Foundation; either version 2 of
00007     the License or (at your option) version 3 or any later version
00008     accepted by the membership of KDE e.V. (or its successor approved
00009     by the membership of KDE e.V.), which shall act as a proxy
00010     defined in Section 14 of version 3 of the license.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 #include "stationlistwidget.h"
00022 
00023 #include <QApplication>
00024 #include <QClipboard>
00025 #include <QContextMenuEvent>
00026 #include <QScrollBar>
00027 #include <QStringList>
00028 #include <QTimer>
00029 #include <KAction>
00030 #include <KLocale>
00031 #include <KStandardAction>
00032 #include "settings_general.h"
00033 #define AND  &&
00034 #define OR  ||
00035 #define NOT  !
00036 #define EQUAL  ==
00037 
00038 stationlistWidget::stationlistWidget(KActionCollection *actionCollection,
00039                                      QWidget *parent,
00040                                      QWidget *mainWindow)
00041   : QTreeView(parent)
00042 {
00043 
00044   // variables
00045   QPointer<CustomizableHeaderView> theHorizontalHeader;
00046   int i;
00047   Qt::SortOrder order;
00048 
00049   // code
00050   theHorizontalHeader = new CustomizableHeaderView(Qt::Horizontal);
00051   // this also deletes automatically the previously used (standard) QHeaderView object:
00052   setHeader(theHorizontalHeader);
00053   theHorizontalHeader->setContextMenuTitle(
00054     i18nc("@title:menu Title of the context menu where you can change visibility of columns",
00055           "Columns"));
00056   if (settings_general::sortingAscendingly()) {
00057     order = Qt::AscendingOrder;
00058   } else {
00059     order = Qt::DescendingOrder;
00060   };
00061   theHorizontalHeader->setSortIndicator(settings_general::sortByColumn(), order);
00062   theHorizontalHeader->setSortIndicatorShown(true);
00063   theHorizontalHeader->setClickable(true);
00064   /* We have to save the width of a column _befor_ it is hidden (after hiding,
00065   *  we wouln't be able to get the width anymore). */
00066   connect(theHorizontalHeader,
00067           SIGNAL(sectionAboutToBeHidden(int, Qt::Orientation)),
00068           this,
00069           SLOT(saveColumnSize(int)));
00070 
00071   setSelectionBehavior(QAbstractItemView::SelectRows);  // don't change this.
00072   // Much code relys on the assumption that only hole rows can be selected.
00073 
00074   m_stationlistModel = new stationlistModel(this, mainWindow);
00075 
00076   // restore column width
00077   for (i=0; i < m_stationlistModel->columnCount(); ++i) {
00078     setColumnHidden(
00079       i,
00080       !m_stationlistModel->columnInfo(stationlistModel::columnVisibility, i).toBool());
00081     setColumnWidth(
00082       i,
00083       m_stationlistModel->columnInfo(stationlistModel::columnWidth, i).toLongLong());
00084   };
00085 
00086   // various settings
00087   setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
00088   setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
00089   setDragDropMode(QAbstractItemView::DropOnly);
00090   setDragDropOverwriteMode(false); // don't override items, but insert new ones!
00091   setAcceptDrops(true);
00092   setSortingEnabled(true);
00093   setItemsExpandable(true);
00094   setAutoExpandDelay(1);
00095   setAnimated(true);
00096   setSelectionMode(QAbstractItemView::ExtendedSelection);
00097   setDropIndicatorShown(true);
00098   setAutoScroll(true);
00099   setAutoExpandDelay(500);
00100   setupActions(actionCollection);
00101 }
00102 
00103 stationlistWidget::~stationlistWidget()
00104 {
00105 }
00106 
00107 void stationlistWidget::saveAllColumnSizes()
00108 {
00109   // variables
00110   int i;
00111 
00112   // code
00113   for (i=0; i < m_stationlistModel->columnCount(); i++) {
00114     if (NOT isColumnHidden(i)) {
00115       saveColumnSize(i);
00116     };
00117     m_stationlistModel->columnInfo(stationlistModel::setColumnVisibility,
00118                                    i,
00119                                    0,
00120                                    NOT isColumnHidden(i));
00121   };
00122 }
00123 
00124 void stationlistWidget::saveColumnSize(const int column)
00125 {
00126   m_stationlistModel->columnInfo(stationlistModel::setColumnWidth,
00127                                  column,
00128                                  0,
00129                                  columnWidth(column));
00130 }
00131 
00132 void stationlistWidget::recalculateActionsStatus()
00133 {
00134   const QModelIndexList list = selectionModel()->selectedRows();
00135   const int number_of_selected_items = list.size();
00136   switch (number_of_selected_items) {
00137     case 0:
00138       emit noneSelected(true);
00139       deleteAction->setEnabled(false);
00140       deleteAction->setData(false);
00141       newStreamAction->setData(true);
00142       newFolderAction->setData(true);
00143       pasteAction->setData(true);
00144       streamSettingsAction->setEnabled(false);
00145       streamSettingsAction->setData(false);
00146       break;
00147     case 1:
00148       emit oneSelected(true);
00149       deleteAction->setEnabled(true);
00150       deleteAction->setData(true);
00151       streamSettingsAction->setEnabled(true);
00152       streamSettingsAction->setData(true);
00153       if (static_cast<stationlistItem *>(list.at(0).internalPointer())->type() ==
00154             stationlistItem::folder) {
00155         newStreamAction->setData(true);
00156         newFolderAction->setData(true);
00157         pasteAction->setData(true);
00158       } else {
00159         newStreamAction->setData(false);
00160         newFolderAction->setData(false);
00161         pasteAction->setData(false);
00162       };
00163       break;
00164     default:
00165       emit multipleSelected(true);
00166       deleteAction->setEnabled(true);
00167       deleteAction->setData(true);
00168       newStreamAction->setData(false);
00169       newFolderAction->setData(false);
00170       pasteAction->setData(false);
00171       streamSettingsAction->setEnabled(false);
00172       streamSettingsAction->setData(false);
00173       break;
00174   };
00175 }
00176 
00177 void stationlistWidget::deleteStation()
00178 {
00179   // variables
00180   QModelIndexList m_list;
00181 
00182   // code
00183   // initialized with a list of the selected rows (for column 0):
00184   m_list = selectionModel()->selectedRows();
00185   while (m_list.size() > 0) {
00186     m_stationlistModel->removeRow(m_list.at(0).row(), m_list.at(0).parent());
00187     m_list = selectionModel()->selectedRows();
00188   };
00189 }
00190 
00191 void stationlistWidget::contextMenuEvent(QContextMenuEvent * e)
00192 {
00193   contextMenu.clear();
00194 
00195   if (recordAction->data().toBool()) {
00196     contextMenu.addAction(recordAction);
00197   };
00198   if (stopRecordAction->data().toBool()) {
00199     contextMenu.addAction(stopRecordAction);
00200   };
00201   if (startListenInAction->data().toBool()) {
00202     contextMenu.addAction(startListenInAction);
00203   };
00204   if (stopListenInAction->data().toBool()) {
00205     contextMenu.addAction(stopListenInAction);
00206   };
00207   if (newStreamAction->data().toBool()) {
00208     contextMenu.addAction(newStreamAction);
00209   };
00210   // change default behaviour that was set up by setupActions
00211   disconnect(newStreamAction, 0, 0, 0);
00212   connect(newStreamAction, SIGNAL(triggered(bool)),
00213           m_stationlistModel, SLOT(addNewStationInFolder()));
00214   if (newFolderAction->data().toBool()) {
00215     contextMenu.addAction(newFolderAction);
00216   };
00217   disconnect(newFolderAction, 0, 0, 0);
00218   connect(newFolderAction, SIGNAL(triggered(bool)),
00219           m_stationlistModel, SLOT(addNewFolderInFolder()));
00220   if (deleteAction->data().toBool()) {
00221     contextMenu.addAction(deleteAction);
00222   };
00223   if (pasteAction->data().toBool()) {
00224     contextMenu.addAction(pasteAction);
00225   };
00226   contextMenu.addAction(selectAllAction);
00227   if (streamSettingsAction->data().toBool()) {
00228     contextMenu.addAction(streamSettingsAction);
00229   };
00230 
00231   contextMenu.exec(e->globalPos());
00232 
00233   // restore default behaviour of setupActions
00234   disconnect(newStreamAction, 0, 0, 0);
00235   connect(newStreamAction, SIGNAL(triggered(bool)),
00236           m_stationlistModel, SLOT(addNewStation()));
00237   disconnect(newFolderAction, 0, 0, 0);
00238   connect(newFolderAction, SIGNAL(triggered(bool)),
00239           m_stationlistModel, SLOT(addNewFolder()));
00240 }
00241 
00242 QPointer<stationlistModel> stationlistWidget::stationlistmodel()
00243 {
00244   return m_stationlistModel;
00245 }
00246 
00247 bool stationlistWidget::queryClose()
00248 {
00249   saveAllColumnSizes();
00250   return stationlistmodel()->queryClose();
00251 }
00252 
00253 void stationlistWidget::saveProperties(KConfigGroup & m_configGroup)
00254 {
00255   saveAllColumnSizes();
00256   stationlistmodel()->saveProperties(m_configGroup);
00257 }
00258 
00259 void stationlistWidget::readProperties(const KConfigGroup & m_configGroup)
00260 {
00261   stationlistmodel()->readProperties(m_configGroup);
00262 }
00263 
00264 void stationlistWidget::mousePressEvent(QMouseEvent *event)
00265 {
00266   if (event->button() == Qt::MidButton) {
00267     stationlistmodel()->pasteSelection(indexAt(viewport()->mapFromGlobal(event->globalPos())));
00268   } else {
00269     // pass on other buttons to base class
00270     QTreeView::mousePressEvent(event);
00271   };
00272 }
00273 
00274 void stationlistWidget::scrollToRow(const QModelIndex & index)
00275 {
00276   int temp = horizontalScrollBar()->sliderPosition();
00277   scrollTo(index);
00278   horizontalScrollBar()->setSliderPosition(temp);
00279 }
00280 
00281 void stationlistWidget::reloadStatusOfPasteAction()
00282 {
00283   bool isAccepted = false;
00284   const QStringList clipboardFormats = QApplication::clipboard()->mimeData()->formats();
00285   const QStringList acceptedFormats = stationlistmodel()->mimeTypes();
00286   const int numberOfAcceptedFormats = acceptedFormats.size();
00287   int i = 0;
00288   while ((!isAccepted) && (i < numberOfAcceptedFormats)) {
00289     isAccepted = clipboardFormats.contains(acceptedFormats.at(i));
00290     ++i;
00291   };
00292   pasteAction->setEnabled(isAccepted);
00293 }
00294 
00295 void stationlistWidget::reloadStatusOfListenInAction()
00296 {
00297   const QModelIndexList list = selectionModel()->selectedRows();
00298   const int number_of_selected_items = list.size();
00299   switch (number_of_selected_items) {
00300     case 0:
00301       startListenInAction->setEnabled(false);
00302       startListenInAction->setData(false);
00303       break;
00304     case 1:
00305       startListenInAction->setData(true);
00306       startListenInAction->setEnabled(false);
00307       if (static_cast<stationlistItem *>(list.at(0).internalPointer())->type() ==
00308             stationlistItem::stream) {
00309         if (static_cast<stationlistItem *>(list.at(0).internalPointer())->
00310             streamObject()->relayPort().type == PropertyValue::value) {
00311           startListenInAction->setEnabled(true);
00312         };
00313       };
00314       break;
00315     default:
00316       startListenInAction->setEnabled(false);
00317       startListenInAction->setData(false);
00318       break;
00319   };
00320 }
00321 
00322 void stationlistWidget::setupActions(KActionCollection *actionCollection)
00323 {
00324   // record
00325   recordAction = new KAction(this);
00326   recordAction->setText(i18nc("@action", "&Record"));
00327   recordAction->setIcon(KIcon("media-record"));
00328   QList<QKeySequence> recordAction_tempShortcutList;
00329   recordAction_tempShortcutList.append(Qt::Key_R);
00330   recordAction_tempShortcutList.append(Qt::Key_MediaRecord);
00331   recordAction_tempShortcutList.append(Qt::CTRL + Qt::Key_R);
00332   recordAction->setShortcuts(recordAction_tempShortcutList);
00333   recordAction->setEnabled(false);
00334   connect(recordAction, SIGNAL(triggered(bool)),
00335           stationlistmodel(), SLOT(record()));
00336   actionCollection->addAction("record", recordAction);
00337 
00338   // stopRecord
00339   stopRecordAction = new KAction(this);
00340   stopRecordAction->setText(i18nc("@action", "&Stop"));
00341   stopRecordAction->setIcon(KIcon("media-playback-stop"));
00342   QList<QKeySequence> stopRecordAction_tempShortcutList;
00343   stopRecordAction_tempShortcutList.append(Qt::Key_S);
00344   stopRecordAction_tempShortcutList.append(Qt::Key_MediaStop);
00345   stopRecordAction_tempShortcutList.append(Qt::CTRL + Qt::Key_S);
00346   stopRecordAction_tempShortcutList.append(Qt::META + Qt::Key_V);
00347   stopRecordAction->setShortcuts(stopRecordAction_tempShortcutList);
00348   stopRecordAction->setEnabled(false);
00349   connect(stopRecordAction, SIGNAL(triggered(bool)),
00350           stationlistmodel(), SLOT(stopRecording()));
00351   actionCollection->addAction("stopRecord", stopRecordAction);
00352 
00353   connect(stationlistmodel(), SIGNAL(selectedStreamsChanged()),
00354           this, SLOT(reloadStatusOfStartAndStopActions()));
00355   connect(stationlistmodel(), SIGNAL(statusChanged()),
00356           this, SLOT(reloadStatusOfStartAndStopActions()));
00357 
00358   // startListenIn
00359   startListenInAction = new KAction(this);
00360 
00361   startListenInAction->setText(
00362     i18nc("@action listening in the stream that is actually recorded (and has been selected)",
00363           "&Listen in"));
00364   startListenInAction->setIcon(KIcon("audio-volume-high"));
00365   /*QList<QKeySequence> startListenInAction_tempShortcutList; TODO
00366   startListenInAction_tempShortcutList.append(Qt::Key_S);
00367   startListenInAction_tempShortcutList.append(Qt::Key_MediaRecord);
00368   startListenInAction_tempShortcutList.append(Qt::CTRL + Qt::Key_S);
00369   startListenInAction_tempShortcutList.append(Qt::META + Qt::Key_V);
00370   startListenInAction->setShortcuts(startListenInAction_tempShortcutList);*/
00371   startListenInAction->setEnabled(false);
00372   connect(startListenInAction, SIGNAL(triggered(bool)),
00373           stationlistmodel(), SLOT(enableListeningIn()));
00374   actionCollection->addAction("startListenIn", startListenInAction);
00375   connect(selectionModel(),
00376           SIGNAL(selectionChanged(const QItemSelection &,const QItemSelection &)),
00377           this,
00378           SLOT(reloadStatusOfListenInAction()));
00379   connect(stationlistmodel(),
00380           SIGNAL(relayportChanged()),
00381           this,
00382           SLOT(reloadStatusOfListenInAction()));
00383 
00384   // stopListenIn
00385   stopListenInAction = new KAction(this);
00386   stopListenInAction->setText(
00387     i18nc("@action listening in the stream that is actually recorded", "&Mute"));
00388   stopListenInAction->setIcon(KIcon("audio-volume-muted"));
00389   /*QList<QKeySequence> stopListenInAction_tempShortcutList; TODO
00390   stopListenInAction_tempShortcutList.append(Qt::Key_S);
00391   stopListenInAction_tempShortcutList.append(Qt::Key_MediaRecord);
00392   stopListenInAction_tempShortcutList.append(Qt::CTRL + Qt::Key_S);
00393   stopListenInAction_tempShortcutList.append(Qt::META + Qt::Key_V);
00394   stopListenInAction->setShortcuts(stopListenInAction_tempShortcutList);*/
00395   stopListenInAction->setEnabled(false);
00396   stopListenInAction->setData(true);
00397   connect(stopListenInAction, SIGNAL(triggered(bool)),
00398           stationlistmodel(), SLOT(disableListeningIn()));
00399   connect(&(stationlistmodel()->listen), SIGNAL(isPlayingChanged(bool)),
00400           this, SLOT(enableStopListenInAction(bool)));
00401   actionCollection->addAction("stopListenIn", stopListenInAction);
00402 
00403   // newStream
00404   // slot will be temporaly changed by contextMenuEvent
00405   newStreamAction = KStandardAction::openNew(
00406     m_stationlistModel,
00407     SLOT(addNewStation()),
00408     this);
00409   newStreamAction->setText(i18nc("@action", "&New stream"));
00410   newStreamAction->setData(true);
00411   actionCollection->addAction("newStream", newStreamAction);
00412 
00413   // newFolder
00414   newFolderAction = new KAction(this);
00415   newFolderAction->setText(i18nc("@action", "New &Folder"));
00416   newFolderAction->setIcon(KIcon("folder-new"));
00417   //newFolderAction->setShortcut(); TODO
00418   newFolderAction->setData(true);
00419   // slot will be temporaly changed by contextMenuEvent
00420   connect(newFolderAction, SIGNAL(triggered(bool)),
00421           m_stationlistModel, SLOT(addNewFolder()));
00422   actionCollection->addAction("newFolder", newFolderAction);
00423 
00424   // delete
00425   deleteAction = new KAction(this);
00426   deleteAction->setText(i18nc("@action", "&Delete"));
00427   deleteAction->setIcon(KIcon("edit-delete"));
00428   deleteAction->setShortcut(Qt::SHIFT + Qt::Key_Delete);
00429   deleteAction->setEnabled(false);
00430   connect(deleteAction, SIGNAL(triggered(bool)),
00431           this, SLOT(deleteStation()));
00432   actionCollection->addAction("deleteStream", deleteAction);
00433 
00434   // paste
00435   pasteAction = KStandardAction::paste(stationlistmodel(), SLOT(paste()), this);
00436   pasteAction->setData(true);
00437   actionCollection->addAction("paste", pasteAction);
00438   connect(QApplication::clipboard(), SIGNAL(dataChanged()),
00439           this, SLOT(reloadStatusOfPasteAction()));
00440   reloadStatusOfPasteAction();
00441 
00442   // selectAll
00443   selectAllAction = KStandardAction::selectAll(this, SLOT(selectAll()), actionCollection);
00444   selectAllAction->setData(true);
00445 
00446   // streamSettings
00447   streamSettingsAction = new KAction(this);
00448   streamSettingsAction->setText(i18nc("@action properties of a stream)", "&Properties"));
00449   streamSettingsAction->setIcon(KIcon("document-properties"));
00450   QList<QKeySequence> streamSettingsAction_tempShortcutList;
00451   streamSettingsAction_tempShortcutList.append(Qt::ALT + Qt::Key_Return);
00452   streamSettingsAction->setShortcuts(streamSettingsAction_tempShortcutList);
00453   streamSettingsAction->setEnabled(false);
00454   connect(streamSettingsAction, SIGNAL(triggered(bool)),
00455           m_stationlistModel, SLOT(showConfigDialog()));
00456   actionCollection->addAction("streamSettings", streamSettingsAction);
00457 
00458   connect(selectionModel(),
00459           SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
00460           this,
00461           SLOT(recalculateActionsStatus()));
00462   recalculateActionsStatus();  // reload status of the actions
00463 }
00464 
00465 void stationlistWidget::reloadStatusOfStartAndStopActions()
00466 {
00467   // variables
00468   const QList<radioStation *> selectedStreams = stationlistmodel()->selectedStreams();
00469   bool start = false;
00470   bool stop = false;
00471 
00472   // code
00473   if (selectionModel()->selectedRows().size() == 0) {
00474     recordAction->setEnabled(false);
00475     recordAction->setData(false);
00476     stopRecordAction->setEnabled(false);
00477     stopRecordAction->setData(false);
00478   } else {
00479     foreach (const radioStation *stream, selectedStreams) {
00480       if (!start) {
00481         start = !stream->isRunning();
00482       };
00483       if (!stop) {
00484         stop = stream->doesTheUserWantsThatTheStreamIsRipping();
00485       };
00486       if (start && stop) {
00487         break;
00488       };
00489     };
00490     recordAction->setEnabled(start);
00491     stopRecordAction->setEnabled(stop);
00492     recordAction->setData(true);
00493     stopRecordAction->setData(true);
00494   };
00495 }
00496 
00497 void stationlistWidget::enableStopListenInAction(bool enabled)
00498 {
00499   stopListenInAction->setEnabled(enabled);
00500 }

doxygen