]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQUI_builtins.cc
remove one FIXME
[duncan/yast2-qt4.git] / src / YQUI_builtins.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:         YUIQt_builtins.cc
14
15   Author:       Stefan Hundhammer <sh@suse.de>
16
17   Textdomain    "packages-qt"
18
19 /-*/
20
21 #define USE_QT_CURSORS          1
22 #define FORCE_UNICODE_FONT      0
23
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include <QCursor>
28 #include <QFileDialog>
29 #include <QX11Info>
30 #include <QMessageBox>
31 #include <QPixmap>
32 #include <QInputDialog>
33
34 #include <ycp/YCPTerm.h>
35 #define y2log_component "qt-ui"
36 #include <ycp/y2log.h>
37
38 #include "YQUI.h"
39 #include "YEvent.h"
40 #include "YMacroRecorder.h"
41 #include "YUISymbols.h"
42 #include "YQDialog.h"
43 #include "YQSignalBlocker.h"
44
45 #include "utf8.h"
46 #include "YQi18n.h"
47
48 #include <X11/Xlib.h>
49
50
51 #define DEFAULT_MACRO_FILE_NAME         "macro.ycp"
52
53
54
55 YCPString
56 YQUI::glyph( const YCPSymbol & glyphSymbol )
57 {
58     string sym = glyphSymbol->symbol();
59     QChar unicodeChar;
60
61     // Hint: Use 'xfd' to view characters available in the Unicode font.
62
63     if      ( sym == YUIGlyph_ArrowLeft         )       unicodeChar = QChar( 0x2190 );
64     else if ( sym == YUIGlyph_ArrowRight        )       unicodeChar = QChar( 0x2192 );
65     else if ( sym == YUIGlyph_ArrowUp           )       unicodeChar = QChar( 0x2191 );
66     else if ( sym == YUIGlyph_ArrowDown         )       unicodeChar = QChar( 0x2193 );
67     else if ( sym == YUIGlyph_CheckMark         )       unicodeChar = QChar( 0x2714 );
68     else if ( sym == YUIGlyph_BulletArrowRight  )       unicodeChar = QChar( 0x279c );
69     else if ( sym == YUIGlyph_BulletCircle      )       unicodeChar = QChar( 0x274d );
70     else if ( sym == YUIGlyph_BulletSquare      )       unicodeChar = QChar( 0x274f );
71     else return YCPString( "" );
72
73     QString qstr( unicodeChar );
74
75     return YCPString( toUTF8( qstr ) );
76 }
77
78
79 YCPValue YQUI::runPkgSelection( YWidget * packageSelector )
80 {
81     y2milestone( "Running package selection..." );
82     YCPValue input = YCPVoid();
83
84     try
85     {
86         input = evaluateUserInput();
87     }
88     catch (const std::exception & e)
89     {
90         y2error( "Caught std::exception: %s", e.what() );
91         y2error( "This is a libzypp problem. Do not file a bug against the UI!" );
92     }
93     catch (...)
94     {
95         y2error( "Caught unspecified exception." );
96         y2error( "This is a libzypp problem. Do not file a bug against the UI!" );
97     }
98
99     y2milestone( "Package selection done - returning %s", input->toString().c_str() );
100
101     return input;
102 }
103
104
105 void YQUI::makeScreenShot( std::string stl_filename )
106 {
107
108     //
109     // Grab the pixels off the screen
110     //
111
112     QWidget * dialog = (QWidget *) YDialog::currentDialog()->widgetRep();
113     QPixmap screenShot = QPixmap::grabWindow( dialog->winId() );
114     XSync( QX11Info::display(), false );
115     QString fileName ( stl_filename.c_str() );
116     bool interactive = false;
117
118     if ( fileName.isEmpty() )
119     {
120         interactive = true;
121
122         // Open a file selection box. Figure out a reasonable default
123         // directory / file name.
124
125         if ( screenShotNameTemplate.isEmpty() )
126         {
127             //
128             // Initialize screen shot directory
129             //
130
131             QString home = QDir::homePath();
132             char * ssdir = getenv("Y2SCREENSHOTS");
133             QString dir  = ssdir ? ssdir : "yast2-screen-shots";
134
135             if ( home == "/" )
136             {
137                 // Special case: $HOME is not set. This is normal in the inst-sys.
138                 // In this case, rather than simply dumping all screen shots into
139                 // /tmp which is world-writable, let's try to create a subdirectory
140                 // below /tmp with restrictive permissions.
141                 // If that fails, trust nobody - in particular, do not suggest /tmp
142                 // as the default in the file selection box.
143
144                 dir = "/tmp/" + dir;
145
146                 if ( mkdir( qPrintable(dir), 0700 ) == -1 )
147                     dir = "";
148             }
149             else
150             {
151                 // For all others let's create a directory ~/yast2-screen-shots and
152                 // simply ignore if this is already present. This gives the user a
153                 // chance to create symlinks to a better location if he wishes so.
154
155                 dir = home + "/" + dir;
156                 (void) mkdir( qPrintable(dir), 0750 );
157             }
158
159             screenShotNameTemplate = dir + "/%s-%03d.png";
160         }
161
162
163         //
164         // Figure out a file name
165         //
166
167         const char * baseName = moduleName();
168         if ( ! baseName ) baseName = "scr";
169         int no = screenShotNo[ baseName ];
170         fileName.sprintf( qPrintable(screenShotNameTemplate), baseName, no );
171         y2debug( "screenshot: %s", qPrintable(fileName) );
172
173         {
174             YQSignalBlocker sigBlocker( &_user_input_timer );
175
176             fileName = askForSaveFileName( fileName, QString( "*.png" ) , _( "Save screen shot to..." ) );
177         }
178
179         if ( fileName.isEmpty() )
180         {
181             y2debug( "Save screen shot canceled by user" );
182             return;
183         }
184
185         screenShotNo.insert( baseName, ++no );
186     } // if fileName.isEmpty()
187
188
189     //
190     // Actually save the screen shot
191     //
192
193     y2debug( "Saving screen shot to %s", qPrintable(fileName) );
194     bool success = screenShot.save( fileName, "PNG" );
195
196     if ( ! success )
197     {
198         y2error( "Couldn't save screen shot %s", qPrintable(fileName) );
199
200         if ( interactive )
201         {
202             QMessageBox::warning( 0,                                    // parent
203                                   "Error",                              // caption
204                                   QString( "Couldn't save screen shot\nto %1" ).arg( fileName ),
205                                   QMessageBox::Ok | QMessageBox::Default,       // button0
206                                   Qt::NoButton,                         // button1
207                                   Qt::NoButton );                       // button2
208         }
209     }
210
211     if ( recordingMacro() )
212     {
213         macroRecorder->beginBlock();
214         YDialog::currentDialog()->saveUserInput( macroRecorder );
215         macroRecorder->recordMakeScreenShot( true, qPrintable(fileName) );
216         macroRecorder->recordUserInput( YCPVoid() );
217         macroRecorder->endBlock();
218     }
219 }
220
221
222 void YQUI::askSaveLogs()
223 {
224     QString fileName = askForSaveFileName( "/tmp/y2logs.tgz",                   // startWith
225                                            "*.tgz *.tar.gz",                    // filter
226                                            "Save y2logs to..." );               // headline
227
228     if ( ! fileName.isEmpty() )
229     {
230         QString saveLogsCommand = "/sbin/save_y2logs";
231
232         if ( access( saveLogsCommand.toAscii(), X_OK ) == 0 )
233         {
234             saveLogsCommand += " '" + fileName + "'";
235             y2milestone( "Saving y2logs: %s", qPrintable(saveLogsCommand) );
236             int result = system( qPrintable(saveLogsCommand) );
237
238             if ( result != 0 )
239             {
240                 y2error( "Error saving y2logs: \"%s\" exited with %d",
241                          qPrintable(saveLogsCommand), result );
242                 QMessageBox::warning( 0,                                        // parent
243                                       "Error",                                  // caption
244                                       QString( "Couldn't save y2logs to %1 - "
245                                                "exit code %2" ).arg( fileName ).arg( result ),
246                                       QMessageBox::Ok | QMessageBox::Default,   // button0
247                                       QMessageBox::NoButton,                    // button1
248                                       QMessageBox::NoButton );                  // button2
249             }
250             else
251             {
252                 y2milestone( "y2logs saved to %s", qPrintable(fileName) );
253             }
254         }
255         else
256         {
257             y2error( "Error saving y2logs: Command %s not found",
258                      qPrintable(saveLogsCommand) );
259
260             QMessageBox::warning( 0,                                            // parent
261                                   "Error",                                      // caption
262                                   QString( "Couldn't save y2logs to %1:\n"
263                                            "Command %2 not found" ).arg( fileName ).arg( saveLogsCommand ),
264                                   QMessageBox::Ok | QMessageBox::Default,       // button0
265                                   QMessageBox::NoButton,                        // button1
266                                   QMessageBox::NoButton );                      // button2
267         }
268     }
269 }
270
271
272 void YQUI::askConfigureLogging()
273 {
274     bool okButtonPressed = false;
275     QStringList items;
276     items << "Debug logging off"
277           << "Debug logging on";
278
279     QString result = QInputDialog::getItem( _main_win,
280                                           tr("YaST2 Logging"),
281                                           tr("Configure YaST2 Logging:"),
282                                           items, 0, get_log_debug() ? 1 : 0, &okButtonPressed);
283     if ( okButtonPressed )
284     {
285         set_log_debug( result.endsWith( "on" ) );
286         y2milestone( "Changing logging: %s - %s", qPrintable(result),
287                      get_log_debug() ? "y2debug on" : "y2debug off" );
288     }
289 }
290
291
292 void YQUI::toggleRecordMacro()
293 {
294     if ( recordingMacro() )
295     {
296         stopRecordMacro();
297         normalCursor();
298
299         QMessageBox::information( 0,                                            // parent
300                                   "YaST2 Macro Recorder",                       // caption
301                                   "Macro recording done.",                      // text
302                                   QMessageBox::Ok | QMessageBox::Default,       // button0
303                                   QMessageBox::NoButton,                        // button1
304                                   QMessageBox::NoButton );                      // button2
305     }
306     else
307     {
308         normalCursor();
309
310         QString filename =
311             QFileDialog::getSaveFileName( 0,
312                                           "Select Macro File to Record to",
313                                           DEFAULT_MACRO_FILE_NAME,              // startWith
314                                           "*.ycp"                             // filter
315                                           );
316
317         if ( ! filename.isEmpty() )     // file selection dialog has been cancelled
318         {
319             recordMacro( qPrintable(filename) );
320         }
321     }
322 }
323
324
325 void YQUI::askPlayMacro()
326 {
327     normalCursor();
328
329     QString filename =
330         QFileDialog::getOpenFileName( 0,
331                                       "Select Macro File to Play",
332                                       DEFAULT_MACRO_FILE_NAME,          // startWith
333                                       "*.ycp" );
334     busyCursor();
335
336     if ( ! filename.isEmpty() ) // file selection dialog has been cancelled
337     {
338         playMacro( qPrintable(filename) );
339
340         // Do special magic to get out of any UserInput() loop right now
341         // without doing any harm - otherwise this would hang until the next
342         // mouse click on a PushButton etc.
343
344         sendEvent( new YEvent() );
345
346         if ( _do_exit_loop )
347         {
348             _eventLoop->exit();
349         }
350     }
351 }
352
353
354
355 YCPValue YQUI::askForExistingDirectory( const YCPString & startDir,
356                                          const YCPString & headline )
357 {
358     normalCursor();
359
360     QString dir_name =
361         QFileDialog::getExistingDirectory( _main_win,
362                                            fromUTF8( headline->value() ),
363                                            fromUTF8( startDir->value() ) );
364     busyCursor();
365
366     if ( dir_name.isEmpty() )   // this includes dir_name.isNull()
367         return YCPVoid();       // nothing selected -> return 'nil'
368
369     return YCPString( toUTF8( dir_name ) );
370 }
371
372
373 YCPValue YQUI::askForExistingFile( const YCPString & startWith,
374                                    const YCPString & filter,
375                                    const YCPString & headline )
376 {
377     normalCursor();
378
379     QString file_name =
380         QFileDialog::getOpenFileName( _main_win,                        // parent
381                                       fromUTF8( headline->value() ),
382                                       fromUTF8( startWith->value() ),
383                                       fromUTF8( filter->value() ) );
384     busyCursor();
385
386     if ( file_name.isEmpty() )  // this includes file_name.isNull()
387         return YCPVoid();       // nothing selected -> return 'nil'
388
389     return YCPString( toUTF8( file_name ) );
390 }
391
392
393 YCPValue YQUI::askForSaveFileName( const YCPString & startWith,
394                                    const YCPString & filter,
395                                    const YCPString & headline )
396 {
397     normalCursor();
398
399     QString file_name = askForSaveFileName( fromUTF8( startWith->value() ),
400                                             fromUTF8( filter->value() ),
401                                             fromUTF8( headline->value() ) );
402     busyCursor();
403
404     if ( file_name.isEmpty() )          // this includes file_name.isNull()
405         return YCPVoid();               // nothing selected -> return 'nil'
406
407     return YCPString( toUTF8( file_name ) );
408 }
409
410
411
412 QString YQUI::askForSaveFileName( const QString & startWith,
413                                   const QString & filter,
414                                   const QString & headline )
415 {
416     QString file_name;
417     bool try_again = false;
418
419     do
420     {
421         // Leave the mouse cursor alone - this function might be called from
422         // some other widget, not only from UI::AskForSaveFileName().
423
424         file_name = QFileDialog::getSaveFileName( _main_win,
425                                                   headline,
426                                                   startWith,
427                                                   filter );
428
429         if ( file_name.isEmpty() )      // this includes file_name.isNull()
430             return QString::null;
431
432
433         if ( access( qPrintable(file_name), F_OK ) == 0 )    // file exists?
434         {
435             QString msg;
436
437             if ( access( qPrintable(file_name), W_OK ) == 0 )
438             {
439                 // Confirm if the user wishes to overwrite an existing file
440                 msg = ( _( "%1 exists! Really overwrite?" ) ).arg( file_name );
441             }
442             else
443             {
444                 // Confirm if the user wishes to overwrite a write-protected file %1
445                 msg = ( _( "%1 exists and is write-protected!\nReally overwrite?" ) ).arg( file_name );
446             }
447
448             int button_no = QMessageBox::information( _main_win,
449                                                       // Window title for confirmation dialog
450                                                       _( "Confirm"   ),
451                                                       msg,
452                                                       _( "C&ontinue" ),
453                                                       _( "&Cancel"   ) );
454             try_again = ( button_no != 0 );
455         }
456
457     } while ( try_again );
458
459     return file_name;
460 }
461
462
463 // EOF