/**************************************************************************** ** ** This file is part of the LibreCAD project, a 2D CAD program ** ** Copyright (C) 2011 Rallaz (rallazz@gmail.com) ** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl) ** Copyright (C) 2001-2003 RibbonSoft. All rights reserved. ** ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file gpl-2.0.txt included in the ** packaging of this file. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ** ** This copyright notice MUST APPEAR in all copies of the script! ** **********************************************************************/ #include "qg_librarywidget.h" #include #include #include #include #include #include #include #include #include #include "rs_system.h" #include "rs_settings.h" #include "rs_painterqt.h" #include "rs_staticgraphicview.h" #include "rs_actionlibraryinsert.h" #include "qg_actionhandler.h" /* * Constructs a QG_LibraryWidget as a child of 'parent', with the * name 'name' and widget flags set to 'f'. * * @author Rallaz */ QG_LibraryWidget::QG_LibraryWidget(QWidget* parent, const char* name, Qt::WindowFlags fl) : QWidget(parent, fl) { setObjectName(name); actionHandler = NULL; QVBoxLayout *vboxLayout = new QVBoxLayout(this); vboxLayout->setSpacing(2); vboxLayout->setContentsMargins(2, 2, 2, 2); dirView = new QTreeView(this); dirView->setRootIsDecorated(true); dirView->setEditTriggers(QAbstractItemView::NoEditTriggers); vboxLayout->addWidget(dirView); ivPreview = new QListView(this); ivPreview->setViewMode(QListView::IconMode); vboxLayout->addWidget(ivPreview); bInsert = new QPushButton(tr("Insert"), this); vboxLayout->addWidget(bInsert); dirModel = new QStandardItemModel; iconModel = new QStandardItemModel; QStringList directoryList = RS_SYSTEM->getDirectoryList("library"); for (int i = 0; i < directoryList.size(); ++i) { appendTree(NULL, directoryList.at(i)); } RS_SETTINGS->beginGroup("/Paths"); QString customPath=RS_SETTINGS->readEntry("/Library", ""); RS_SETTINGS->endGroup(); if(customPath.size()>0){ //todo: make the custom path more flexible appendTree(NULL,customPath); } dirView->setModel(dirModel); ivPreview->setModel(iconModel); dirModel->setHorizontalHeaderLabels ( QStringList(tr("Directories"))); connect(dirView, SIGNAL(expanded(QModelIndex)), this, SLOT(expandView(QModelIndex))); connect(dirView, SIGNAL(collapsed(QModelIndex)), this, SLOT(collapseView(QModelIndex))); connect(dirView, SIGNAL(clicked(QModelIndex)), this, SLOT(updatePreview(QModelIndex))); connect(bInsert, SIGNAL(clicked()), this, SLOT(insert())); } /* * Destroys the object and frees any allocated resources * * @author Rallaz */ QG_LibraryWidget::~QG_LibraryWidget() { // no need to delete child widgets, Qt does it all for us // delete model; //?????? /* QStandardItemModel *model; QTreeView *dirView; QListView *ivPreview;*/ } /* * Sets the strings of the subwidgets using the current * language. * @author Rallaz */ void QG_LibraryWidget::languageChange() { // retranslateUi(this); } void QG_LibraryWidget::setActionHandler(QG_ActionHandler* ah) { actionHandler = ah; } /** * Escape releases focus. */ void QG_LibraryWidget::keyPressEvent(QKeyEvent* e) { switch (e->key()) { case Qt::Key_Escape: emit escape(); break; default: QWidget::keyPressEvent(e); break; } } /** * Insert. */ void QG_LibraryWidget::insert() { QItemSelectionModel* selIconView = ivPreview->selectionModel(); QModelIndex idx = selIconView->currentIndex(); QStandardItem * item = iconModel->itemFromIndex ( idx ); if (item == 0) return; QString dxfPath = getItemPath(item); if (QFileInfo(dxfPath).isReadable()) { if (actionHandler!=NULL) { RS_ActionInterface* a = actionHandler->setCurrentAction(RS2::ActionLibraryInsert); if (a!=NULL) { RS_ActionLibraryInsert* action = (RS_ActionLibraryInsert*)a; action->setFile(dxfPath); } else { RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LibraryWidget::insert:" "Cannot create action RS_ActionLibraryInsert"); } } } else { RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LibraryWidget::insert: Can't read file: '%s'", dxfPath.toLatin1().data()); } } /** * Appends the given directory to the given list view item. Called recursively until all * library directories are appended. * * @author Rallaz */ void QG_LibraryWidget::appendTree(QStandardItem* item, QString directory) { // QStringList::Iterator it; QDir dir(directory); if (!dir.exists()) return; // read subdirectories of this directory: QStringList lDirectoryList = dir.entryList(QDir::Dirs|QDir::NoDotAndDotDot, QDir::Name); QStandardItem* newItem; QStandardItem* searchItem; if (item == NULL) item = dirModel->invisibleRootItem(); for (int i = 0; i < lDirectoryList.size(); ++i) { newItem=NULL; // Look for an item already existing and take this // instead of making a new one: for (int j = 0; j < item->rowCount(); ++j) { searchItem = item->child (j); if (searchItem->text() == lDirectoryList.at(i)) { newItem=searchItem; break; } } // Create new item if no existing was found: if (newItem==NULL) { newItem = new QStandardItem(QIcon(":/ui/folderclosed.png"), lDirectoryList.at(i)); item->setChild(item->rowCount(), newItem); } appendTree(newItem, directory+QDir::separator()+lDirectoryList.at(i)); } item->sortChildren ( 0, Qt::AscendingOrder ); } /** * Change the icon item when is expanded. * * @author Rallaz */ void QG_LibraryWidget::expandView( QModelIndex idx ){ QStandardItem * item = dirModel->itemFromIndex ( idx ); if (item != 0) item->setIcon(QIcon(":/ui/folderopen.png")); } /** * Change the icon item when is collapsed. * * @author Rallaz */ void QG_LibraryWidget::collapseView( QModelIndex idx ){ QStandardItem * item = dirModel->itemFromIndex ( idx ); if (item != 0) item->setIcon(QIcon(":/ui/folderclosed.png")); } /** * Updates the icon preview. * * @author Rallaz */ void QG_LibraryWidget::updatePreview(QModelIndex idx) { QStandardItem * item = dirModel->itemFromIndex ( idx ); if (item == 0) return; QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); // dir from the point of view of the library browser (e.g. /mechanical/screws) QString directory = getItemDir(item); //RLZ change to do-while iconModel->clear(); // List of all directories that contain part libraries: QStringList directoryList = RS_SYSTEM->getDirectoryList("library"); QDir itemDir; QStringList itemPathList; // look in all possible system directories for DXF files in the current library path: for (int i = 0; i < directoryList.size(); ++i) { itemDir.setPath(directoryList.at(i)+directory); if (itemDir.exists()) { QStringList itemNameList = itemDir.entryList(QStringList("*.dxf"), QDir::Files, QDir::Name); for (int j = 0; j < itemNameList.size(); ++j) { itemPathList += itemDir.path()+QDir::separator()+itemNameList.at(j); } } } // Sort entries: itemPathList.sort(); // Fill items into icon view: QStandardItem* newItem; for (int i = 0; i < itemPathList.size(); ++i) { QString label = QFileInfo(itemPathList.at(i)).baseName(); QIcon icon = getIcon(directory, QFileInfo(itemPathList.at(i)).fileName(), itemPathList.at(i)); newItem = new QStandardItem(icon, label); iconModel->setItem(i, newItem); } QApplication::restoreOverrideCursor(); } //RLZ change to do-while /** * @return Directory (in terms of the List view) to the given item (e.g. /mechanical/screws) */ QString QG_LibraryWidget::getItemDir(QStandardItem* item) { QString ret = ""; if (item==NULL) { return ret; } QStandardItem* parent = item->parent(); return getItemDir(parent) + QDir::separator() + QString("%1").arg(item->text()); } /** * @return Path of the DXF file that is represented by the given item. */ QString QG_LibraryWidget::getItemPath(QStandardItem* item) { QItemSelectionModel* selDirView = dirView->selectionModel(); QModelIndex idx = selDirView->currentIndex(); QStandardItem * dirItem = dirModel->itemFromIndex ( idx ); QString dir = getItemDir(dirItem); if (item!=NULL) { // List of all directories that contain part libraries: QStringList directoryList = RS_SYSTEM->getDirectoryList("library"); QStringList::Iterator it; QDir itemDir; // look in all possible system directories for DXF files in the current library path: for (it=directoryList.begin(); it!=directoryList.end(); ++it) { itemDir.setPath((*it)+dir); if (itemDir.exists()) { QString f = (*it) + dir + QDir::separator() + item->text() + ".dxf"; if (QFileInfo(f).isReadable()) { return f; } } } return ""; } else { return ""; } } /** * @return Pixmap that serves as icon for the given DXF File. * The existing PNG file is returned or created and returned.. * * @param dir Library directory (e.g. "/mechanical/screws") * @param dxfFile File name (e.g. "screw1.dxf") * @param dxfPath Full path to the existing DXF file on disk * (e.g. /home/tux/.qcad/library/mechanical/screws/screw1.dxf) */ QIcon QG_LibraryWidget::getIcon(const QString& dir, const QString& dxfFile, const QString& dxfPath) { QString pngFile = getPathToPixmap(dir, dxfFile, dxfPath); QFileInfo fiPng(pngFile); // found existing thumbnail: if (fiPng.isFile()) { return QIcon(pngFile); } // default thumbnail: else { return QIcon(QPixmap(64,64)); } } /** * @return Path to the thumbnail of the given DXF file. If no thumbnail exists, one is * created in the user's home. If no thumbnail can be created, an empty string is returned. */ QString QG_LibraryWidget::getPathToPixmap(const QString& dir, const QString& dxfFile, const QString& dxfPath) { // the thumbnail must be created in the user's home. QString iconCacheLocation=QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QDir::separator() + "iconCache" + QDir::separator(); RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: " "dir: '%s' dxfFile: '%s' dxfPath: '%s'", dir.toLatin1().data(), dxfFile.toLatin1().data(), dxfPath.toLatin1().data()); // List of all directories that contain part libraries: QStringList directoryList = RS_SYSTEM->getDirectoryList("library"); directoryList.prepend(iconCacheLocation); QStringList::Iterator it; QFileInfo fiDxf(dxfPath); QString itemDir; QString pngPath; // look in all possible system directories for PNG files // in the current library path: for (it=directoryList.begin(); it!=directoryList.end(); ++it) { itemDir = (*it)+dir; pngPath = itemDir + QDir::separator() + fiDxf.baseName() + ".png"; RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: checking: '%s'", pngPath.toLatin1().data()); QFileInfo fiPng(pngPath); // the thumbnail exists: if (fiPng.isFile()) { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: dxf date: %s, png date: %s", fiDxf.lastModified().toString().toLatin1().data(), fiPng.lastModified().toString().toLatin1().data()); if (fiPng.lastModified() > fiDxf.lastModified()) { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: thumbnail found: '%s'", pngPath.toLatin1().data()); return pngPath; } else { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: thumbnail needs to be updated: '%s'", pngPath.toLatin1().data()); } } } // create all directories needed: RS_SYSTEM->createPaths(iconCacheLocation + dir); QString foo=iconCacheLocation + dir + QDir::separator() + fiDxf.baseName() + ".png"; pngPath = iconCacheLocation + dir + QDir::separator() + fiDxf.baseName() + ".png"; QPixmap* buffer = new QPixmap(128,128); RS_PainterQt painter(buffer); painter.setBackground(RS_Color(255,255,255)); painter.eraseRect(0,0, 128,128); RS_StaticGraphicView gv(128,128, &painter); RS_Graphic graphic; if (graphic.open(dxfPath, RS2::FormatUnknown)) { for (RS_Entity* e=graphic.firstEntity(RS2::ResolveAll); e!=NULL; e=graphic.nextEntity(RS2::ResolveAll)) { RS_Pen pen = e->getPen(); pen.setColor(Qt::black); e->setPen(pen); } gv.setContainer(&graphic); gv.zoomAuto(false); // gv.drawEntity(&graphic, true); for (RS_Entity* e=graphic.firstEntity(RS2::ResolveAll); e!=NULL; e=graphic.nextEntity(RS2::ResolveAll)) { gv.drawEntity(&painter, e); } QImageWriter iio; QImage img; img = buffer->toImage(); img = img.scaled(64,64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); // iio.setImage(img); iio.setFileName(pngPath); iio.setFormat("PNG"); if (!iio.write(img)) { pngPath = ""; RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LibraryWidget::getPathToPixmap: Cannot write thumbnail: '%s'", pngPath.toLatin1().data()); } } else { RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LibraryWidget::getPathToPixmap: Cannot open file: '%s'", dxfPath.toLatin1().data()); } // GraphicView deletes painter painter.end(); delete buffer; return pngPath; }