File indexing completed on 2024-05-12 16:23:31
0001 /*************************************************************************** 0002 * Copyright (C) 2005-2017 by Linuxstopmotion contributors; * 0003 * see the AUTHORS file for details. * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 #include "devicetab.h" 0021 0022 #include <algorithm> 0023 #include <memory> 0024 #include <string> 0025 0026 #include "flexiblelineedit.h" 0027 #include "graphics/icons/close.xpm" 0028 #include "src/domain/domainfacade.h" 0029 #include "src/foundation/preferencestool.h" 0030 #include "src/foundation/logger.h" 0031 #include "src/technical/util.h" 0032 0033 #include <QHeaderView> 0034 #include <QTableWidget> 0035 #include <QLineEdit> 0036 #include <QPushButton> 0037 #include <QLabel> 0038 #include <QGridLayout> 0039 #include <QGroupBox> 0040 #include <QTextEdit> 0041 0042 0043 DeviceTab::DeviceTab(QWidget *parent) 0044 : QWidget(parent) 0045 { 0046 deviceTable = 0; 0047 addButton = 0; 0048 removeButton = 0; 0049 editButton = 0; 0050 closeChangeBoxButton = 0; 0051 deviceEdit = 0; 0052 devicePreferences = 0; 0053 deviceLabel = 0; 0054 checkTableItem = 0; 0055 informationText = 0; 0056 0057 numAutoDetectedDevices = -1; 0058 makeGUI(); 0059 } 0060 0061 0062 void DeviceTab::makeGUI() 0063 { 0064 this->setFocusPolicy(Qt::ClickFocus); 0065 0066 informationText = new QTextEdit; 0067 informationText->setReadOnly(true); 0068 informationText->setHtml( 0069 "<p>" + tr("Below you can set which device Stopmotion should use for grabbing images " 0070 "and displaying video.") + "<br><br>" + 0071 tr("You can select from the auto-detected devices below or add devices yourself. " 0072 "It is not recommended to use devices which is not auto-detected, but feel free to do " 0073 "it if you are an advanced user.") + "<br><br>" + 0074 tr("The selected device is recognized as <b>$VIDEODEVICE</b> under Video Import.") + 0075 "</p>"); 0076 informationText->setMinimumWidth(440); 0077 informationText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 0078 0079 QStringList lst; 0080 lst << tr("Name") << tr("Description"); 0081 0082 deviceTable = new QTableWidget; 0083 deviceTable->setColumnCount(2); 0084 deviceTable->setRowCount(0); 0085 deviceTable->setSelectionMode(QAbstractItemView::SingleSelection); 0086 deviceTable->setSelectionBehavior(QAbstractItemView::SelectRows); 0087 deviceTable->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum); 0088 deviceTable->setHorizontalHeaderLabels(lst); 0089 deviceTable->verticalHeader()->setVisible(false); 0090 0091 connect(deviceTable, SIGNAL(cellClicked(int, int)), this, SLOT(activeCellChanged(int, int))); 0092 connect(deviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(contentsChanged(int, int))); 0093 0094 addButton = new QPushButton(tr("&Add")); 0095 addButton->setFocusPolicy( Qt::NoFocus ); 0096 connect(addButton, SIGNAL(clicked()), this, SLOT(addDevice())); 0097 0098 removeButton = new QPushButton(tr("&Remove")); 0099 connect( removeButton, SIGNAL(clicked()), this, SLOT(removeDevice())); 0100 0101 editButton = new QPushButton(tr("&Edit")); 0102 QObject::connect( editButton, SIGNAL(clicked()), this, SLOT(editDevice())); 0103 0104 devicePreferences = new QGroupBox; 0105 devicePreferences->setTitle(tr("Video device settings")); 0106 devicePreferences->hide(); 0107 0108 closeChangeBoxButton = new QPushButton; 0109 closeChangeBoxButton->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Minimum); 0110 closeChangeBoxButton->setIcon(QPixmap(closeicon)); 0111 closeChangeBoxButton->setFlat(true); 0112 connect(closeChangeBoxButton, SIGNAL(clicked()),this, SLOT(closeChangeBox())); 0113 0114 deviceLabel = new QLabel( tr("Video Device ($VIDEODEVICE): ") ); 0115 deviceEdit = new FlexibleLineEdit; 0116 connect(deviceEdit, SIGNAL(textChanged(const QString &)), 0117 this, SLOT(updateDeviceString(const QString &))); 0118 0119 QVBoxLayout *mainLayout = new QVBoxLayout; 0120 mainLayout->addWidget(informationText); 0121 QVBoxLayout *buttonLayout = new QVBoxLayout; 0122 buttonLayout->setContentsMargins(0, 0, 0, 0); 0123 buttonLayout->setSpacing(2); 0124 buttonLayout->addStretch(1); 0125 buttonLayout->addWidget(addButton); 0126 buttonLayout->addWidget(removeButton); 0127 buttonLayout->addWidget(editButton); 0128 QHBoxLayout *deviceLayout = new QHBoxLayout; 0129 deviceLayout->addWidget(deviceTable); 0130 deviceLayout->addLayout(buttonLayout); 0131 mainLayout->addLayout(deviceLayout); 0132 mainLayout->addWidget(devicePreferences); 0133 setLayout(mainLayout); 0134 0135 QVBoxLayout *devicePrefsLayout = new QVBoxLayout; 0136 QHBoxLayout *hbLayout = new QHBoxLayout; 0137 hbLayout->setContentsMargins(0, 0, 0, 0); 0138 hbLayout->setSpacing(0); 0139 hbLayout->addStretch(1); 0140 hbLayout->addWidget(closeChangeBoxButton); 0141 devicePrefsLayout->addLayout(hbLayout); 0142 devicePrefsLayout->addWidget(deviceLabel); 0143 devicePrefsLayout->addWidget(deviceEdit); 0144 devicePreferences->setLayout(devicePrefsLayout); 0145 } 0146 0147 0148 void DeviceTab::initialize() { 0149 Logger::get().logDebug("Initializing video device settings"); 0150 PreferencesTool *pref = PreferencesTool::get(); 0151 0152 std::vector<GrabberDevice> devices = DomainFacade::getFacade()->getGrabberDevices(); 0153 numAutoDetectedDevices = devices.size(); 0154 deviceTable->setRowCount(numAutoDetectedDevices); 0155 0156 // Auto-detected devices 0157 for (int i = 0; i < numAutoDetectedDevices; ++i) { 0158 QString name( devices[i].name.c_str() ); 0159 QString device( devices[i].device.c_str() ); 0160 QString desc(QString("*Autodetected* ") + devices[i].type.c_str() + "-" + 0161 tr("device") + " (" + device + ")"); 0162 0163 QTableWidgetItem *item = new QTableWidgetItem(name); 0164 item->setFlags( item->flags() & (~Qt::ItemIsEditable) ); 0165 deviceTable->setItem(i, 0, item); 0166 0167 item = new QTableWidgetItem(desc); 0168 item->setFlags( item->flags() & (~Qt::ItemIsEditable) ); 0169 deviceTable->setItem(i, 1, item); 0170 0171 deviceNameStrings.push_back(name); 0172 deviceStrings.push_back(device); 0173 deviceDescriptionStrings.push_back(desc); 0174 } 0175 0176 // Userdefined devices 0177 int active = pref->getPreference("activeVideoDevice", -1); 0178 int numDevices = pref->getPreference("numDevices", 0); 0179 int numUserDevices = 0; 0180 int newActive = -1; 0181 std::string oldDevice; 0182 std::string oldName; 0183 bool oldWasAutoDetected = false; 0184 0185 for (int i = 0; i < numDevices; ++i) { 0186 Preference descP(QString("deviceDescription%1").arg(i).toUtf8().constData(),""); 0187 QString desc(descP.get()); 0188 Preference nameP(QString("deviceName%1").arg(i).toUtf8().constData(),""); 0189 QString name(nameP.get()); 0190 Preference deviceP(QString("device%1").arg(i).toUtf8().constData(),""); 0191 QString device(deviceP.get()); 0192 if (active == i) { 0193 oldDevice = device.toStdString(); 0194 oldName = name.toStdString(); 0195 } 0196 0197 if ( !desc.startsWith("*Autodetected*") ) { 0198 if (active == i) 0199 newActive = numUserDevices + numAutoDetectedDevices; 0200 deviceTable->setRowCount( numUserDevices + numAutoDetectedDevices + 1 ); 0201 deviceTable->setItem(numUserDevices + numAutoDetectedDevices, 0202 0, new QTableWidgetItem(name)); 0203 deviceTable->setItem(numUserDevices + numAutoDetectedDevices, 0204 1, new QTableWidgetItem(desc)); 0205 ++numUserDevices; 0206 0207 deviceNameStrings.push_back(name); 0208 deviceStrings.push_back(device); 0209 deviceDescriptionStrings.push_back(desc); 0210 } else if (active == i) { 0211 oldWasAutoDetected = true; 0212 } 0213 } 0214 0215 if (oldWasAutoDetected && 0 < numAutoDetectedDevices) { 0216 // try to find a reasonable match for the last chosen auto detected 0217 // device 0218 int bestScore = 0; 0219 newActive = numAutoDetectedDevices - 1; 0220 for (int i = 0; i != numAutoDetectedDevices; ++i) { 0221 int score = 0; 0222 if (oldName == devices[i].name) 0223 score = 2; 0224 if (oldDevice == devices[i].device) 0225 score += 1; 0226 if (bestScore < score) { 0227 newActive = i; 0228 } 0229 } 0230 } 0231 if (0 <= newActive) 0232 deviceTable->setCurrentCell(newActive, 0); 0233 } 0234 0235 0236 void DeviceTab::apply() { 0237 PreferencesTool *prefs = PreferencesTool::get(); 0238 0239 // Remove old preferences 0240 int numDevices = prefs->getPreference("numDevices", -1); 0241 if (numDevices > 0) { 0242 for (int i = 0; i < numDevices; ++i) { 0243 prefs->removePreference(QString("deviceName%1").arg(i).toUtf8().constData()); 0244 prefs->removePreference(QString("deviceDescription%1").arg(i).toUtf8().constData()); 0245 prefs->removePreference(QString("device%1").arg(i).toUtf8().constData()); 0246 } 0247 } 0248 0249 // Set new preferences 0250 numDevices = deviceTable->rowCount(); 0251 if (numDevices > 0) { 0252 prefs->setPreference("numDevices", numDevices); 0253 prefs->setPreference("activeVideoDevice", deviceTable->currentRow()); 0254 for (int i = 0; i < numDevices; ++i) { 0255 prefs->setPreference(QString("deviceName%1").arg(i).toUtf8().constData(), 0256 deviceTable->item(i, 0)->text().toUtf8().constData()); 0257 prefs->setPreference(QString("deviceDescription%1").arg(i).toUtf8().constData(), 0258 deviceTable->item(i, 1)->text().toUtf8().constData()); 0259 prefs->setPreference(QString("device%1").arg(i).toUtf8().constData(), 0260 deviceStrings[i].toUtf8().constData()); 0261 } 0262 } else { 0263 prefs->setPreference("numDevices", -1); 0264 prefs->setPreference("activeVideoDevice", -1); 0265 } 0266 } 0267 0268 0269 void DeviceTab::resizeEvent(QResizeEvent *event) 0270 { 0271 contentsChanged(0, 0); 0272 QWidget::resizeEvent(event); 0273 } 0274 0275 0276 void DeviceTab::contentsChanged(int, int) 0277 { 0278 deviceTable->resizeColumnsToContents(); 0279 int totalWidth = deviceTable->columnWidth(0) + deviceTable->columnWidth(1); 0280 int tableWidth = deviceTable->width() - 5; 0281 if ( totalWidth < tableWidth) { 0282 deviceTable->setColumnWidth( 1, tableWidth - deviceTable->columnWidth(0) ); 0283 } 0284 } 0285 0286 0287 void DeviceTab::activeCellChanged(int, int) 0288 { 0289 if ( devicePreferences->isVisible() ) { 0290 editDevice(); 0291 } 0292 } 0293 0294 0295 void DeviceTab::editDevice() 0296 { 0297 int selected = deviceTable->currentRow(); 0298 if (selected >= 0) { 0299 deviceEdit->setText(deviceStrings[selected]); 0300 devicePreferences->show(); 0301 0302 // Disables editing of autodetected devices 0303 if (selected < numAutoDetectedDevices) { 0304 deviceEdit->setReadOnly(true); 0305 } 0306 else { 0307 deviceEdit->setReadOnly(false); 0308 } 0309 } 0310 } 0311 0312 0313 void DeviceTab::closeChangeBox() 0314 { 0315 devicePreferences->hide(); 0316 this->resize(minimumSize()); 0317 } 0318 0319 0320 void DeviceTab::updateDeviceString(const QString &txt) 0321 { 0322 deviceStrings[deviceTable->currentRow()] = txt; 0323 } 0324 0325 0326 void DeviceTab::addDevice() 0327 { 0328 int newRow = deviceTable->rowCount(); 0329 deviceTable->setRowCount(newRow + 1); 0330 deviceTable->setItem( newRow, 0, new QTableWidgetItem(QString("")) ); 0331 deviceTable->setItem( newRow, 1, new QTableWidgetItem(QString("")) ); 0332 deviceTable->setCurrentCell(newRow, 0); 0333 0334 deviceStrings.push_back(""); 0335 deviceNameStrings.push_back(""); 0336 deviceDescriptionStrings.push_back(""); 0337 } 0338 0339 0340 void DeviceTab::removeDevice() 0341 { 0342 int selectedRow = deviceTable->currentRow(); 0343 if (selectedRow >= 0 && selectedRow >= numAutoDetectedDevices) { 0344 deviceStrings.erase(deviceStrings.begin() + selectedRow); 0345 deviceNameStrings.erase(deviceNameStrings.begin() + selectedRow); 0346 deviceDescriptionStrings.erase(deviceDescriptionStrings.begin() + selectedRow); 0347 deviceTable->removeRow(selectedRow); 0348 contentsChanged(0, 0); 0349 } 0350 } 0351 0352 0353 void DeviceTab::retranslateStrings() 0354 { 0355 informationText->setHtml( 0356 "<p>" + tr("Below you can set which device Stopmotion should use for grabbing images " 0357 "and displaying video.") + "<br><br>" + 0358 tr("You can select from the auto-detected devices below or add devices yourself. " 0359 "It is not recommended to use devices which is not auto-detected, but feel free to do " 0360 "it if you are an advanced user.") + "<br><br>" + 0361 tr("The selected device is recognized as <b>$VIDEODEVICE</b> under Video Import.") + 0362 "</p>"); 0363 0364 QStringList lst; 0365 lst << tr("Name") << tr("Description"); 0366 deviceTable->setHorizontalHeaderLabels(lst); 0367 0368 addButton->setText( tr("&Add") ); 0369 removeButton->setText( tr("&Remove") ); 0370 editButton->setText( tr("&Edit") ); 0371 0372 0373 devicePreferences->setTitle(tr("Video device settings")); 0374 deviceLabel->setText( tr("Video Device ($VIDEODEVICE): ") ); 0375 }