3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/10/2010 Created this file. :-)
15 // JLH 08/28/2010 Restored functionality to library browser
16 // JLH 09/06/2010 Partially fixed thumbnail rendering
17 // JLH 09/07/2010 Fully fixed thumbnail rendering
21 Note that this is basically just a way to get a block from a file; it's unclear
22 that it does so and the doco (such as it was) didn't mention it either. So what
23 we need is to make it very clear that inserting is to the BLOCK list and not
24 the document--perhaps we need to fold it into the block list, and make the
25 insert function insert into the block list only...
28 #include "librarywidget.h"
30 #include "actionhandler.h"
31 #include "actionlibraryinsert.h"
33 #include "rs_staticgraphicview.h"
34 #include "rs_system.h"
35 #include "paintinterface.h"
37 LibraryWidget::LibraryWidget(QWidget * parent/*= 0*/, Qt::WindowFlags flags/*= 0*/):
38 QWidget(parent, flags), actionHandler(NULL)
41 std::cout << "LibraryWidget::LibraryWidget()" << std::endl;
44 ui.lvDirectory->setColumnCount(1);
46 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
48 std::cout << "directorySize = " << directoryList.size() << std::endl;
50 for(int i=0; i<directoryList.size(); i++)
51 std::cout << directoryList.at(i).toLocal8Bit().constData() << std::endl;
56 for(QStringList::Iterator it=directoryList.begin(); it!=directoryList.end(); it++)
57 appendTree(NULL, (*it));
60 LibraryWidget::~LibraryWidget()
64 void LibraryWidget::setActionHandler(ActionHandler * ah)
70 * Escape releases focus.
72 void LibraryWidget::keyPressEvent(QKeyEvent * e)
81 QWidget::keyPressEvent(e);
89 void LibraryWidget::insert()
91 QListWidgetItem * item = ui.ivPreview->currentItem();
92 QString dxfPath = getItemPath(item);
94 if (QFileInfo(dxfPath).isReadable())
98 ActionInterface * a = actionHandler->setCurrentAction(RS2::ActionLibraryInsert);
102 ActionLibraryInsert * action = (ActionLibraryInsert *)a;
103 action->setFile(dxfPath);
107 RS_DEBUG->print(RS_Debug::D_ERROR, "LibraryWidget::insert:"
108 "Cannot create action ActionLibraryInsert");
114 RS_DEBUG->print(RS_Debug::D_ERROR,
115 "LibraryWidget::insert: Can't read file: '%s'", dxfPath.toLatin1().data());
120 * Appends the given directory to the given list view item. Called recursively until all
121 * library directories are appended.
123 void LibraryWidget::appendTree(QTreeWidgetItem * item, QString directory)
130 // read subdirectories of this directory:
131 QStringList lDirectoryList = dir.entryList(QDir::Dirs, QDir::Name);
133 for(QStringList::Iterator it=lDirectoryList.begin(); it!=lDirectoryList.end(); it++)
135 if ((*it) != "." && (*it) != "..")
137 // Look for an item already existing and take this instead of
139 QTreeWidgetItem * newItem = NULL;
140 QTreeWidgetItem * searchItem =
141 (item ? item->child(0) : ui.lvDirectory->topLevelItem(0));
145 for(int i=0; i<searchItem->childCount(); i++)
147 if (searchItem->child(i)->text(0) == (*it))
149 newItem = searchItem->child(i);
155 // Create new item if no existing was found:
160 newItem = (item ? new QTreeWidgetItem(item, list) : new QTreeWidgetItem(ui.lvDirectory, list));
163 //This is picking up the directory tree TWICE, but ONLY if there are no thumbnails!
164 //Actually, only if there is no corresponding thumbnail DIRECTORY under .architektonas...
166 //It was picking up .architektonas from the home directory in rs_system.cpp, that's why!
167 //printf("LibraryWidget::appendTree: *it=\"%s\"\n", (*it).toAscii().data());
168 appendTree(newItem, directory + "/" + (*it));
174 * Updates the icon preview.
176 void LibraryWidget::updatePreview(QTreeWidgetItem * item, int /*column*/)
181 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
183 // dir from the point of view of the library browser (e.g. /mechanical/screws)
184 QString directory = getItemDir(item);
185 ui.ivPreview->clear();
187 // List of all directories that contain part libraries:
188 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
189 QStringList::Iterator it;
191 QStringList itemPathList;
195 // Look in all possible system directories for DXF files in the current library path:
196 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
198 itemDir.setPath((*it) + directory);
200 if (itemDir.exists())
202 QStringList itemNameList = itemDir.entryList(filter, QDir::Files, QDir::Name);
203 QStringList::Iterator it2;
205 for(it2=itemNameList.begin(); it2!=itemNameList.end(); ++it2)
206 itemPathList += itemDir.path() + "/" + (*it2);
213 // Fill items into icon view:
214 QListWidgetItem * newItem;
216 for(it=itemPathList.begin(); it!=itemPathList.end(); ++it)
218 // QString label = QFileInfo(*it).baseName(true);
219 QString label = QFileInfo(*it).completeBaseName();
220 QPixmap pixmap = getPixmap(directory, QFileInfo(*it).fileName(), (*it));
221 // newItem = new QListWidgetItem(ui.ivPreview, label, pixmap);
222 newItem = new QListWidgetItem(QIcon(pixmap), label, ui.ivPreview);
223 //Doesn't do what we want...
224 // newItem->setSizeHint(QSize(64, 64));
225 //printf("LibraryWidget: label = \"%s\"\n", label.toAscii().data());
228 QApplication::restoreOverrideCursor();
232 * @return Directory (in terms of the List view) to the given item (e.g. /mechanical/screws)
233 * (called recursively)
235 QString LibraryWidget::getItemDir(QTreeWidgetItem * item)
240 QTreeWidgetItem * parent = item->parent();
242 return getItemDir(parent) + QString("/%1").arg(item->text(0));
246 * @return Path of the DXF file that is represented by the given item.
248 QString LibraryWidget::getItemPath(QListWidgetItem * item)
250 QString dir = getItemDir(ui.lvDirectory->currentItem());
254 // List of all directories that contain part libraries:
255 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
256 QStringList::Iterator it;
259 // Look in all possible system directories for DXF files in the current library path:
260 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
262 itemDir.setPath((*it) + dir);
264 if (itemDir.exists())
266 QString f = (*it) + dir + "/" + item->text() + ".dxf";
268 if (QFileInfo(f).isReadable())
278 * @return Pixmap that serves as icon for the given DXF File.
279 * The existing PNG file is returned or created and returned..
281 * @param dir Library directory (e.g. "/mechanical/screws")
282 * @param dxfFile File name (e.g. "screw1.dxf")
283 * @param dxfPath Full path to the existing DXF file on disk
284 * (e.g. /home/tux/.architektonas/library/mechanical/screws/screw1.dxf)
286 QPixmap LibraryWidget::getPixmap(const QString & dir, const QString & dxfFile,
287 const QString & dxfPath)
289 QString pngFile = getPathToPixmap(dir, dxfFile, dxfPath);
290 QFileInfo fiPng(pngFile);
292 // Found existing thumbnail:
294 return QPixmap(pngFile);
295 // Default thumbnail:
297 return QPixmap(64, 64);
301 * @return Path to the thumbnail of the given DXF file. If no thumbnail exists, one is
302 * created in the user's home. If no thumbnail can be created, an empty string is returned.
304 QString LibraryWidget::getPathToPixmap(const QString & dir, const QString & dxfFile,
305 const QString & dxfPath)
307 RS_DEBUG->print("LibraryWidget::getPathToPixmap: dir: '%s' dxfFile: '%s' dxfPath: '%s'",
308 dir.toLatin1().data(), dxfFile.toLatin1().data(), dxfPath.toLatin1().data());
310 // List of all directories that contain part libraries:
311 QStringList directoryList = RS_SYSTEM->getDirectoryList("library");
312 directoryList.prepend(RS_SYSTEM->getHomeDir() + "/.architektonas/library");
313 QStringList::Iterator it;
315 QFileInfo fiDxf(dxfPath);
319 // look in all possible system directories for PNG files
320 // in the current library path:
321 for(it=directoryList.begin(); it!=directoryList.end(); ++it)
323 itemDir = (*it) + dir;
324 pngPath = itemDir + "/" + fiDxf.completeBaseName() + ".png";
325 RS_DEBUG->print("LibraryWidget::getPathToPixmap: checking: '%s'",
326 pngPath.toLatin1().data());
327 QFileInfo fiPng(pngPath);
329 // the thumbnail exists:
332 RS_DEBUG->print("LibraryWidget::getPathToPixmap: dxf date: %s, png date: %s",
333 fiDxf.lastModified().toString().toLatin1().data(), fiPng.lastModified().toString().toLatin1().data());
335 if (fiPng.lastModified() > fiDxf.lastModified())
337 RS_DEBUG->print("LibraryWidget::getPathToPixmap: thumbnail found: '%s'",
338 pngPath.toLatin1().data());
343 RS_DEBUG->print("LibraryWidget::getPathToPixmap: thumbnail needs to be updated: '%s'",
344 pngPath.toLatin1().data());
349 // The thumbnail must be created in the user's home.
350 // So, create all directories needed:
351 RS_SYSTEM->createHomePath("/.architektonas/library" + dir);
352 QString d = RS_SYSTEM->getHomeDir() + "/.architektonas/library" + dir;
353 pngPath = d + "/" + fiDxf.completeBaseName() + ".png";
355 QPixmap buffer(128, 128);
356 QPainter qpntr(&buffer);
357 PaintInterface * painter = new PaintInterface(&qpntr);
358 qpntr.setBackground(Qt::white);
359 qpntr.eraseRect(0, 0, 128, 128);
361 RS_StaticGraphicView view(128, 128, painter);
364 if (drawing.open(dxfPath, RS2::FormatUnknown))
366 RS_Color black(0, 0, 0);
368 // Set all pens in the drawing to BLACK
369 for(RS_Entity * e=drawing.firstEntity(RS2::ResolveAll); e!=NULL; e=drawing.nextEntity(RS2::ResolveAll))
371 RS_Pen pen = e->getPen();
376 view.setContainer(&drawing);
377 view.zoomAuto(false);
378 view.drawEntity(&drawing, true);
381 QImage image = buffer.toImage();
382 image.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
383 writer.setFileName(pngPath);
384 writer.setFormat("png");
386 if (!writer.write(image))
388 RS_DEBUG->print(RS_Debug::D_ERROR,
389 "LibraryWidget::getPathToPixmap: Cannot write thumbnail: '%s'",
390 pngPath.toLatin1().data());
396 RS_DEBUG->print(RS_Debug::D_ERROR, "LibraryWidget::getPathToPixmap: Cannot open file: '%s'", dxfPath.toLatin1().data());