]> Shamusworld >> Repos - architektonas/blob - src/base/rs_fileio.cpp
Fixed thumbnail rendering in LibraryWidget and DXF detection.
[architektonas] / src / base / rs_fileio.cpp
1 // rs_fileio.cpp
2 //
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
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  05/28/2010  Added this text. :-)
15 // JLH  09/07/2010  Fixed file detection algorithm.
16 //
17
18 #include "rs_fileio.h"
19
20 #include "rs_filtercxf.h"
21 #include "rs_filterdxf.h"
22 #include "rs_filterdxf1.h"
23 #include "rs_filterinterface.h"
24
25 RS_FileIO * RS_FileIO::uniqueInstance = NULL;
26
27 // Constructor
28 RS_FileIO::RS_FileIO()
29 {
30 }
31
32 /**
33  * @return Instance to the unique import object.
34  */
35 /*static*/ RS_FileIO * RS_FileIO::instance()
36 {
37         if (!uniqueInstance)
38                 uniqueInstance = new RS_FileIO();
39
40         return uniqueInstance;
41 }
42
43 /**
44  * Registers a new import filter.
45  */
46 void RS_FileIO::registerFilter(RS_FilterInterface * f)
47 {
48         filterList.append(f);
49 }
50
51 /**
52  * @return List of registered filters.
53  */
54 QList<RS_FilterInterface *> RS_FileIO::getFilterList()
55 {
56         return filterList;
57 }
58
59 /**
60  * @return Filter which can import the given file type.
61  */
62 RS_FilterInterface * RS_FileIO::getImportFilter(RS2::FormatType t)
63 {
64         for(int i=0; i<filterList.size(); i++)
65         {
66                 RS_FilterInterface * f = filterList[i];
67
68                 if (f->canImport(t))
69                         return f;
70         }
71
72         return NULL;
73 }
74
75 /**
76  * @return Filter which can export the given file type.
77  */
78 RS_FilterInterface * RS_FileIO::getExportFilter(RS2::FormatType t)
79 {
80         for(int i=0; i<filterList.size(); i++)
81         {
82                 RS_FilterInterface * f = filterList[i];
83
84                 if (f->canExport(t))
85                         return f;
86         }
87
88         return NULL;
89 }
90
91 /**
92  * Calls the import method of the filter responsible for the format
93  * of the given file.
94  *
95  * @param graphic The container to which we will add
96  *        entities. Usually that's an Drawing entity but
97  *        it can also be a polyline, text, ...
98  * @param file Path and name of the file to import.
99  */
100 bool RS_FileIO::fileImport(Drawing & graphic, const QString & file, RS2::FormatType type)
101 {
102         RS_DEBUG->print("Trying to import file '%s'...", file.toAscii().data());
103
104         RS_FilterInterface * filter = NULL;
105         RS2::FormatType t = (type == RS2::FormatUnknown ? detectFormat(file) : type);
106         filter = getImportFilter(t);
107
108     if (filter)
109         return filter->fileImport(graphic, file, t);
110         else
111         {
112                 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_FileIO::fileImport: failed to import file: %s",
113                         file.toAscii().data());
114         }
115
116         return false;
117 }
118
119 /**
120  * Calls the export method of the object responsible for the format
121  * of the given file.
122  *
123  * @param file Path and name of the file to import.
124  */
125 bool RS_FileIO::fileExport(Drawing & graphic, const QString & file, RS2::FormatType type)
126 {
127         RS_DEBUG->print("RS_FileIO::fileExport");
128
129         if (type == RS2::FormatUnknown)
130         {
131                 QString extension = QFileInfo(file).suffix().toLower();
132
133                 if (extension == "dxf")
134                         type = RS2::FormatDXF;
135                 else if (extension == "cxf")
136                         type = RS2::FormatCXF;
137         }
138
139         RS_FilterInterface * filter = getExportFilter(type);
140
141         if (filter)
142                 return filter->fileExport(graphic, file, type);
143
144         RS_DEBUG->print("RS_FileIO::fileExport: no filter found");
145
146         return false;
147 }
148
149 /**
150  * Detects and returns the file format of the given file.
151  */
152 RS2::FormatType RS_FileIO::detectFormat(const QString & file)
153 {
154         RS2::FormatType type = RS2::FormatUnknown;
155         QFileInfo info(file);
156         QString ext = info.suffix().toLower();
157
158         if (ext == "cxf")
159         {
160                 type = RS2::FormatCXF;
161         }
162         else if (ext == "dxf")
163         {
164                 type = RS2::FormatDXF1;
165                 QFile f(file);
166
167                 if (!f.open(QIODevice::ReadOnly))
168                 {
169                         // Error opening file:
170                         RS_DEBUG->print(RS_Debug::D_WARNING,
171                                 "RS_FileIO::detectFormat: Cannot open file: %s", file.toAscii().data());
172                         type = RS2::FormatUnknown;
173                 }
174                 else
175                 {
176                         RS_DEBUG->print("RS_FileIO::detectFormat: Successfully opened DXF file: %s",
177                                 file.toAscii().data());
178
179                         QTextStream ts(&f);
180                         int c = 0;
181
182 //I think this is wrong... We're mixing classes here...
183 //AND THAT WAS THE PROBLEM!!!
184 //                      while (!f.atEnd() && ++c < 100)
185                         while (!ts.atEnd() && ++c < 100)
186                         {
187                                 QString line = ts.readLine();
188
189                                 if (line == "$ACADVER")
190                                         type = RS2::FormatDXF;
191
192                                 // very simple reduced DXF:
193                                 if (line == "ENTITIES" && c < 10)
194                                         type = RS2::FormatDXF;
195                         }
196
197                         f.close();
198                 }
199         }
200
201         return type;
202 }