//-------------------------------------------------------------------------------------- // Update table //-------------------------------------------------------------------------------------- void tNDP2kDevicePage::UpdateDeviceList() { if(tGlobal<tNDP2k>::Instance()->IsBusOff()) { if(m_IsBusOff == false) { // If we just realized about the Bus Off, restart the list so that only the internal devices are shown m_IsBusOff = true; RefreshDeviceList(); return; } } else { m_IsBusOff = false; } tNDP2kDevice* pDevice; for (int row=0; row < m_pTableWidget->rowCount(); ++row) { if (tGlobal<tNDP2k>::Instance()->DeviceManager().NameToDevice(m_pTableWidget->item(row, m_NameColumn)->text(), &pDevice)) { rowChanged(row, pDevice); } } if (m_SortOption >= 0) { Sort(); } }
void DeviceWidget::OpenTrayClicked(){ //Open the CD tray if(isMounted){ mountButtonClicked(); } //unmount the device before opening the tray if(isMounted){ return; } //Could not unmount device: don't open the tray QProcess::startDetached("cdcontrol eject /dev/"+node()); emit CloseMenu(); emit RefreshDeviceList(); }
void DeviceWidget::mountButtonClicked(){ //mount/unmount the device (based on current status) if(isMounted){ QString res = pcbsd::Utils::runShellCommand("pc-sysconfig \"unmount "+node()+"\"").join(""); if(res.simplified()!="[SUCCESS]"){ //Can add additional types of error parsing later (TO-DO) //See if the user wants to try and force the unmount if(QMessageBox::Yes == QMessageBox::question(0, tr("Device Busy"), tr("The device appears to be busy. Do you want to forcibly unmount the device?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No)){ res = pcbsd::Utils::runShellCommand("pc-sysconfig \"unmount "+node()+" force\"").join(""); }else{ return; //don't show the result message if the action was cancelled } } //Now parse the output and emit the proper signals if(res=="[SUCCESS]"){ QuickUpdate(false); //quickly update the UI with the new mount status }else{ QMessageBox::warning(this, tr("Unmount Error"), tr("The device could not be unmounted. Please try again later") ); } }else{ //Device unmounted, need to mount it QString fs = filesystem(); if(fs=="NONE"){ //prompt for what filesystem to try and use to mount the device QStringList fslist = pcbsd::Utils::runShellCommand("pc-sysconfig supportedfilesystems").join("").split(", "); bool ok = false; fs = QInputDialog::getItem(0,tr("No Filesystem Detected"), tr("Select a filesystem to try:"), fslist, 0, false, &ok); if(!ok){ return; } //cancelled } //Now try to mount the device QString res = pcbsd::Utils::runShellCommand("pc-sysconfig \"mount "+node()+" "+fs+"\"").join(""); if(res.startsWith("[SUCCESS]")){ //Save the mountpoint for use later (return format: "[SUCCESS] <mountpoint>" ui->tool_run->setWhatsThis( res.section("]",1,20).simplified() ); QuickUpdate(true); }else{ qDebug() << node()+":" << res; QString err = tr("The device could not be mounted. Please try again later."); QMessageBox::warning(0,tr("Device Mounting Error"), err); } } //end of mount detection emit RefreshDeviceList(); }
//-------------------------------------------------------------------------------------- //! Defines the NDP2k network device page (shows the devices) //-------------------------------------------------------------------------------------- tNDP2kDevicePage::tNDP2kDevicePage(tNDP2k& ndp2k, QWidget* pParent, bool showButtons, const QList<eColumns> customColumnList ) : tDialog(tDialog::Full, pParent) , m_pNDP2k( &ndp2k ) , m_FirstRefresh ( true ) , m_FirstRun( true ) , m_tableRefreshMode( false ) , m_ShowNameColumn( false ) // For debugging purposes , m_ShowButtons( showButtons ) { setWindowTitle( tr( "Device List", "NDP2k device list dialog title" ) ); m_ColumnName[addressColumn] = tr("Address"); m_ColumnName[modelIdColumn] = tr("Model ID"); m_ColumnName[manufacturerColumn] = tr("Manufacturer"); m_ColumnName[productCodeColumn] = tr("Product Code"); m_ColumnName[classFunctionColumn] = tr("Class/Function"); m_ColumnName[nameColumn] = tr("ISO Name"); m_ColumnName[busUsageColumn] = tr("Bus %"); m_ColumnName[deviceInstanceColumn] = tr("Instance"); m_ColumnName[serialNumberColumn] = tr("Serial No."); // keep name last - it is hidden & not in sort list. if( false == customColumnList.isEmpty() ) { m_DisplayColumns = customColumnList; } else { m_DisplayColumns = (QList<eColumns>() << modelIdColumn << serialNumberColumn); } if( tNdp2kSettings::Instance()->GetDebugEnabled() ) { m_DisplayColumns << addressColumn; m_ShowNameColumn = true; } m_DisplayColumns << nameColumn; assert(m_DisplayColumns.contains(nameColumn)); m_NameColumn = m_DisplayColumns.indexOf(nameColumn); m_SortOptionList = QStringList(); m_SortOption = 0; for(int i = 0; i < m_DisplayColumns.count(); i++) { if( m_DisplayColumns[i] != nameColumn || m_ShowNameColumn ) { m_SortOptionList << m_ColumnName[m_DisplayColumns[i]]; } } // if we have a SKB keys don't have focus, else hide keys m_NumKeys = 0; if ( HasSoftKeyBar() ) { m_NumKeys = SoftKeyBar()->numSoftKeys(); SoftKeyBar()->SetSoftKeyFocusPolicy(Qt::NoFocus); } else { SoftKeyBar()->ExplicitHide(); } CreateActions(); Connect( this, SIGNAL( CloseRequested() ), this, SLOT( accept() ) ); m_pTableWidget = new tTableWidget(0, m_DisplayColumns.count(), this); m_pTableWidget->setFocusPolicy(Qt::StrongFocus); m_pTableWidget->setEditTriggers( QAbstractItemView::NoEditTriggers ); m_pTableWidget->verticalHeader()->hide(); m_pTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); m_pTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); m_pTableWidget->SetSoleFocus( true ); m_pTableWidget->SetWrapping( true ); if( tUiSettings::Instance()->ShowTouchToolTips() == true ) { m_pTableWidget->setToolTip( tr("Tap-and-hold for more options.") ); } else { m_pTableWidget->setToolTip( tr("Press %1 for more options.").arg(BUTTON_HTML(tNOSStyle::FP_ButtonImageMENU, "MENU")) ); } Connect( m_pTableWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( SelectionChanged() ) ); Connect( m_pTableWidget, SIGNAL( itemClicked( QTableWidgetItem* ) ), m_pDetailsAct, SLOT( trigger() ) ); QHeaderView* pHeaderView = m_pTableWidget->horizontalHeader(); // Prevents header bold font pHeaderView->setHighlightSections(false); pHeaderView->setDefaultAlignment(Qt::AlignLeft); Connect( pHeaderView, SIGNAL( sectionClicked( int ) ), this, SLOT( SetSortOption( int ) ) ); SetHeaderFont(); for(int i = 0; i < m_DisplayColumns.count(); i++) { switch(m_DisplayColumns[i]) { case addressColumn: case manufacturerColumn: case productCodeColumn: case busUsageColumn: case deviceInstanceColumn: case serialNumberColumn: default: { pHeaderView->setResizeMode(i, QHeaderView::ResizeToContents); } break; case modelIdColumn: case SwVersionColumn: case classFunctionColumn: { pHeaderView->setResizeMode(i, QHeaderView::Stretch); } break; case nameColumn: { if( m_ShowNameColumn ) { pHeaderView->setResizeMode(i, QHeaderView::Stretch); } else { pHeaderView->setResizeMode(i, QHeaderView::Fixed); pHeaderView->resizeSection(i, 0); // hide it this way. (actual hide breaks sorting.) } } break; } } QStringList headings; for(int i = 0; i < m_DisplayColumns.count(); i++) { headings << m_ColumnName[m_DisplayColumns[i]]; } m_pTableWidget->setHorizontalHeaderLabels(headings); QVBoxLayout* pVLayout = new QVBoxLayout; pVLayout->addWidget(m_pTableWidget); setLayout(pVLayout); tNDP2k* pNDP2k = tGlobal<tNDP2k>::Instance(); Connect(&pNDP2k->DeviceManager(), SIGNAL(DeviceListChanged(const tN2kName&)), this, SLOT(OnDeviceChanged(const tN2kName&))); /* Set the bus status on startup... */ if(pNDP2k->IsBusOff()) { m_IsBusOff = true; } else { m_IsBusOff = false; } m_SelectedName = ""; //NSW-7687 (Work around LGC-4k unreliable response to global request for address claim...) // - No longer required - since we no longer do a global request for address claim. RefreshDeviceList(); // initial row selected in UpdateDeviceList, when we have some content startTimer(1000); //TODO: tNotificationAndStatusMonitor::Instance()->SetVesselShow(false); if ( tProductSettings::Instance().GetProductFamily() == tProductSettings::MedusaFamily ) { Connect( tApOperation::Instance(), SIGNAL( ApModeChanged(tPilotCommandInterface::tPilotMode) ), this, SLOT( OnApModeChanged(tPilotCommandInterface::tPilotMode) ) ); OnApModeChanged( tApOperation::Instance()->GetApMode() ); // Init text } if( tProductSettings::Instance().ScreenPixelWidth() < 480 ) { pVLayout->setMargin(0); } }
// == PRIVATE FUNCTIONS == void DeviceWidget::doUpdate(){ bool firstrun = type().isEmpty(); //qDebug() << "Update Item:" << firstrun << quickupdates << node(); if(firstrun || !quickupdates){ QStringList info = pcbsd::Utils::runShellCommand("pc-sysconfig \"devinfo "+node()+"\"").join("").split(", "); if(info.length() < 3){ emit RefreshDeviceList(); return; } //invalid device - will probably get removed here in a moment //Info Output: <filesystem>, <label>, <type> //qDebug() << " - info:" << info; //Save this into the internal variables ui->label_icon->setWhatsThis(info[2]); //type ui->label_dev->setText(info[1]); //label ui->tool_mount->setWhatsThis(info[0]); //filesystem if(info[0].toLower()=="zfs"){ ui->label_icon->setToolTip(node()+" ("+info[0]+")"); } else{ ui->label_icon->setToolTip("/dev/"+node()+" ("+info[0]+")"); } //Now go through and set all the various icons and such QString icon = ":icons/%1.png"; if(type()=="SATA"){ icon = icon.arg("harddrive"); } else if(type()=="USB"){ icon = icon.arg("usb"); } else if(type()=="SD"){ icon = icon.arg("sdcard"); } else if(type()=="CD-AUDIO"){ icon = icon.arg("musiccd"); } else if(type()=="CD-VIDEO"){ icon = icon.arg("cd-video"); } else if(type().startsWith("CD")){ icon = icon.arg("cd-generic"); } else if(type()=="ISO"){ icon = icon.arg("dvd"); } else{ icon = icon.arg("CDdevices"); } if(filesystem()=="NONE" && !type().startsWith("CD")){ //Add the question-mark overlay to the icon, signifying that it is an unknown filesystem QPixmap tmp(icon); QPixmap overlay(":icons/question-overlay.png"); QPainter paint(&tmp); paint.drawPixmap(ui->label_icon->width()-20, ui->label_icon->height()-20, overlay ); //put it in the bottom-right corner ui->label_icon->setPixmap(tmp); }else{ //Just the normal icon ui->label_icon->setPixmap(QPixmap(icon)); } if(type()=="CD-AUDIO" || type()=="CD-VIDEO"){ ui->tool_run->setIcon(QIcon(":icons/play.png")); ui->tool_run->setText(tr("Play")); }else{ ui->tool_run->setIcon(QIcon(":icons/folder.png") ); ui->tool_run->setText(tr("Browse")); } ui->tool_tray->setVisible(type().startsWith("CD")); //This is a CD tray canmount = filesystem()!="NONE" || !type().startsWith("CD"); //has a detected filesystem or is not a CD ui->tool_mount->setVisible(canmount); ui->check_auto->setVisible(canmount && !type().startsWith("CD")); } //Update the status of the mount button (TO DO - special ISO handling) if(isMounted){ ui->tool_mount->setText(tr("Unmount")); ui->tool_mount->setIcon(QIcon(":icons/eject.png")); QString devsize = pcbsd::Utils::runShellCommand("pc-sysconfig \"devsize "+node()+"\"").join(""); if(devsize.contains("??")){ ui->progressBar->setRange(0,0); }else{ ui->progressBar->setRange(0,100); ui->progressBar->setValue(devsize.section("(",1,1).section("%",0,0).toInt()); ui->progressBar->setToolTip(devsize); } }else{ ui->tool_mount->setText(tr("Mount")); ui->tool_mount->setIcon(QIcon(":icons/mount.png")); } ui->label_icon->setEnabled(isMounted || !canmount); ui->tool_run->setVisible( (isMounted && !mountpoint().isEmpty()) || type()=="CD-AUDIO" || type()=="CD-VIDEO" ); //if it is mounted, it can also be run ui->progressBar->setVisible(isMounted && ui->progressBar->maximum()==100); if(firstrun){ if(canmount && !type().startsWith("CD") ){ //Load auto-mount database and act appropriately QString AMFILE = QDir::homePath() + "/.pc-automounttray"; if(QFile::exists(AMFILE)){ QString cmd = "cat "+AMFILE; QString search = label() +" "+ type()+" "+ filesystem(); bool amount = !pcbsd::Utils::runShellCommandSearch(cmd, search).isEmpty(); ui->check_auto->setChecked(amount); if(amount){ mountButtonClicked(); if(isMounted){ emit ShowMessage(tr("Device Mounted"), QString(tr("%1 has been automatically mounted on %2")).arg(label(), mountpoint()) ); runButtonClicked(); //also open the directory } } } }else if(canmount){ //This is some kind of optical disk that can also be mounted (Blueray/DVD, or data disk for instance) if(type()!="CD-DATA"){ runButtonClicked(); } //not a pure data disk - go ahead and prompt to run it }else if(autoplay){ //Always try to "play" a non-mountable device when it is first connected (AUDIO/VIDEO CD usually) runButtonClicked(); } } }
void MountTray::UpdateDeviceMenu(bool fast, bool refresh){ QStringList avail, mounted; QStringList tmp = pcbsd::Utils::runShellCommand("pc-sysconfig list-remdev list-mounteddev"); if(tmp.length()<2 || tmp.join("").contains("Client Connection Error:") ){ return; } //invalid return if(!tmp[0].contains("[NO INFO]")){ avail = tmp[0].split(", "); } if(!tmp[1].contains("[NO INFO]")){ mounted = tmp[1].split(", "); } //qDebug() << "Update Devices:" << avail << mounted; //Update the current menu items as necessary bool newitems = false; for(int i=0; i<DEVLIST.length(); i++){ QString dev = DEVLIST[i]->node(); //qDebug() << "Check device:" << dev; if(avail.contains(dev)){ if(fast){ DEVLIST[i]->QuickUpdate(mounted.contains(dev)); } else{ DEVLIST[i]->UpdateDevice(mounted.contains(dev)); } avail.removeAll(dev); //remove this device from the list for the moment }else{ //Invalid device, remove it from the list disconnect(DEVLIST[i]); trayIconMenu->removeAction(DEVLIST[i]->action()); DEVLIST.removeAt(i); i--; } } //Now create widgets for any new devices for(int i=0; i<avail.length(); i++){ newitems = true; DeviceWidget *item = new DeviceWidget(this, avail[i]); item->setAutoPlay(useAutoPlay); connect(item, SIGNAL(CloseMenu()), this, SLOT(slotCloseMenu()) ); connect(item, SIGNAL(RefreshDeviceList()), this, SLOT(UpdateDeviceMenu()) ); connect(item, SIGNAL(ShowMessage(QString, QString)), this, SLOT(slotDisplayPopup(QString, QString)) ); DEVLIST << item; trayIconMenu->insertAction(menuline, item->action()); //put them above the line item->UpdateDevice( mounted.contains(avail[i]) ); //need the full update to start } //Now update the list of available network shares netMenu->clear(); QStringList info = pcbsd::Utils::runShellCommand("pc-sysconfig list-mountednetdrives").join("").split(", "); qDebug() << "Net Info:" << info; //Syntax for the list: [<name> (<IP>) on <directory>] for(int i=0; i<info.length(); i++){ if(info[i].startsWith("[")){ continue; } //error code from pc-sysconfig QAction *act = new QAction(info[i].section("(",0,0).simplified(), netMenu); act->setWhatsThis( info[i].section(" on ",1,1).simplified() ); act->setToolTip( info[i].section(")",0,0).section("(",1,1).simplified() ); netMenu->addAction(act); } netMenu->setEnabled( !netMenu->isEmpty() ); //Now show a popup message about any new devices if(!avail.isEmpty() && !MTINIT && newitems && !refresh){ slotDisplayPopup(tr("Devices Available"), tr("New Devices are available for use")); } if(useDiskWatcher && useDiskTimerDevd && !MTINIT){ diskWatcher->checkFS(); } //Update the main icon based upon whether devices have been found if(DEVLIST.length()==0){ trayIcon->setIcon( QIcon(":icons/CDdevices-inactive.png") ); }else{ if(mounted.length()==0){ trayIcon->setIcon( QIcon(":icons/CDdevices.png") ); }else{ trayIcon->setIcon( QIcon(":icons/CDdevices.png") ); } } }