diff options
Diffstat (limited to 'src/modules/dialog/libkvidialog.cpp')
-rw-r--r-- | src/modules/dialog/libkvidialog.cpp | 920 |
1 files changed, 920 insertions, 0 deletions
diff --git a/src/modules/dialog/libkvidialog.cpp b/src/modules/dialog/libkvidialog.cpp new file mode 100644 index 00000000..dd7cf391 --- /dev/null +++ b/src/modules/dialog/libkvidialog.cpp @@ -0,0 +1,920 @@ +//============================================================================= +// +// File : libkvidialog.cpp +// Creation date : Sat Sep 15 2001 01:13:25 by Szymon Stefanek +// +// This file is part of the KVirc irc client distribution +// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot net) +// +// This program is FREE software. You can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your opinion) any later version. +// +// 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. +// +//============================================================================= + + +#include "libkvidialog.h" + +#include <qmessagebox.h> +#include <qlayout.h> +#include "kvi_tal_hbox.h" +#include <qlineedit.h> +#ifdef COMPILE_USE_QT4 + #include <q3multilineedit.h> + #define QMultiLineEdit Q3MultiLineEdit + #include <qdesktopwidget.h> +#else + #include <qmultilineedit.h> +#endif +#include <qevent.h> +#include <qlabel.h> +#include <qpushbutton.h> + +#include "kvi_locale.h" +#include "kvi_module.h" +#include "kvi_modulemanager.h" +#include "kvi_error.h" +#include "kvi_app.h" +#include "kvi_iconmanager.h" +#include "kvi_console.h" +#include "kvi_iconmanager.h" +#include "kvi_kvs_script.h" +#include "kvi_msgbox.h" + +static KviPointerList<QWidget> * g_pDialogModuleDialogList; + +KviKvsCallbackMessageBox::KviKvsCallbackMessageBox( + const QString &szCaption, + const QString &szText, + const QString &szIcon, + const QString &szButton0, + const QString &szButton1, + const QString &szButton2, + const QString &szCode, + KviKvsVariantList * pMagicParams, + KviWindow * pWindow,bool modal) +: QMessageBox( + szCaption, + szText, + QMessageBox::NoIcon, + szButton0.isEmpty() ? QMessageBox::NoButton : QMessageBox::Ok | QMessageBox::Default, + szButton1.isEmpty() ? QMessageBox::NoButton : (szButton2.isEmpty() ? QMessageBox::No | QMessageBox::Escape : QMessageBox::No), + szButton2.isEmpty() ? QMessageBox::NoButton : QMessageBox::Cancel | QMessageBox::Escape, + 0,0,modal) , + KviKvsCallbackObject("dialog.message",pWindow,szCode,pMagicParams,0) +{ + g_pDialogModuleDialogList->append(this); +#ifndef COMPILE_USE_QT4 + setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC))); +#endif + + QPixmap * pix = g_pIconManager->getImage(szIcon); + + if(pix)setIconPixmap(*pix); + else { + if(KviQString::equalCI(szIcon,"information"))setIcon(QMessageBox::Information); + else if(KviQString::equalCI(szIcon,"warning"))setIcon(QMessageBox::Warning); + else if(KviQString::equalCI(szIcon,"critical"))setIcon(QMessageBox::Critical); + } + if(!szButton0.isEmpty())setButtonText(QMessageBox::Ok,szButton0); + if(!szButton1.isEmpty())setButtonText(QMessageBox::No,szButton1); + if(!szButton2.isEmpty())setButtonText(QMessageBox::Cancel,szButton2); +} + +KviKvsCallbackMessageBox::~KviKvsCallbackMessageBox() +{ + g_pDialogModuleDialogList->removeRef(this); +} + +void KviKvsCallbackMessageBox::done(int code) +{ + QMessageBox::done(code); + + kvs_int_t iVal = 0; + + switch(code) + { + case QMessageBox::No: iVal = 1; break; + case QMessageBox::Cancel: iVal = 2; break; + } + + KviKvsVariantList params; + params.append(new KviKvsVariant(iVal)); + + execute(¶ms); + + delete this; +} + + +/* + @doc: dialog.message + @type: + command + @title: + dialog.message + @short: + Shows a message box + @syntax: + dialog.message [-b] (<caption>,<message_text>,<icon>,<button0>[,<button1>[,<button2>[,<magic1>[,<magic2>[...]]]]]) + { + <callback_command> + } + @description: + Shows a message dialog box with the specified <caption> , <message_text> , <icon> and + buttons.[br] + <caption> is a text string that will appear in the caption of the dialog box.[br] + <message_text> is a text string that will appear in the dialog box and can contain HTML formatting.[br] + <icon> is an [doc:image_id]image identifier[/doc] that defines an icon to be placed in the dialog box. + <icon> can be a relative or absolute path to an image file , a signed number (in that case it defines + an internal KVIrc image) or one of the special strings "critical", "information" and "warning".[br] + <button0> is the text of the first button (on the left).[br] + <button1> is the text of the second button (if empty or not given at all, only one button will appear in the dialog).[br] + <button2> is the text of the third button (if empty or not given, only two buttons will appear in the dialog).[br] + The first button is always the default button: it is activated when the user presses the + enter key. The thirs, or the second if the third is not present, is the escape button + and is activated when the user presses the Esc key.[br] + <magic1>,<magic2>... are the magic parameters: evaluated at dialog.message call time and passed + to the <callback_command> as positional parameters.[br] + If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour: + it will appear above its parent widget and block its input until it's closed.[br] + Once the dialog has been shown , the user will click one of the buttons. At this point the dialog + is hidden and the <callback_command> is executed passing the number of the button clicked + as $0 and the magic parameters as positional parameters $1 , $2 , $3....[br] + Please note that if the user closes the window with the window manager close button , + the action is interpreted as a button2 click (that is usually sth as "Cancel").[br] + @examples: + [example] + [comment]# Just a warning dialog[/comment] + dialog.message("Warning","You're being <b>warned</b>",warning,"Ok"){ echo The user clicked OK; } + [comment]# A question[/comment] + dialog.message("And now ?","What do you want to do ?",information,"Go home","Watch TV","Scream") + { + if($0 == 0)echo "The user want's to go home" + else if($0 == 1)echo "The user want's to watch TV" + else echo "The user wants to scream!" + } + [/example] +*/ + +static bool dialog_kvs_cmd_message(KviKvsModuleCallbackCommandCall * c) +{ + QString szCaption,szMessage,szIcon,szButton0,szButton1,szButton2; + KviKvsVariantList params; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption) + KVSM_PARAMETER("message",KVS_PT_STRING,0,szMessage) + KVSM_PARAMETER("icon",KVS_PT_STRING,0,szIcon) + KVSM_PARAMETER("button0",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton0) + KVSM_PARAMETER("button1",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton1) + KVSM_PARAMETER("button2",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton2) + KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params) + KVSM_PARAMETERS_END(c) + bool modal; + if(c->hasSwitch('b',"modal")) modal=true; + else modal=false; + QString szCmd = c->callback()->code(); + + KviKvsCallbackMessageBox * box = new KviKvsCallbackMessageBox( + szCaption,szMessage,szIcon,szButton0,szButton1,szButton2,szCmd,¶ms,c->window(),modal); + box->show(); + + return true; +} + + + +KviKvsCallbackTextInput::KviKvsCallbackTextInput( + const QString &szCaption, + const QString &szLabel, + const QString &szDefaultText, + const QString &szIcon, + bool bMultiLine, + const QString &szButton0, + const QString &szButton1, + const QString &szButton2, + const QString &szCode, + KviKvsVariantList * pMagicParams, + KviWindow * pWindow,bool modal) + : QDialog(), KviKvsCallbackObject("dialog.textinput",pWindow,szCode,pMagicParams,0) +{ + g_pDialogModuleDialogList->append(this); + setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC))); + setModal(modal); + setCaption(szCaption); + + QGridLayout * g = new QGridLayout(this,2,3,5,5); + + QPixmap * pix = g_pIconManager->getImage(szIcon); + + if(pix) + { + QLabel * il = new QLabel(this); + il->setPixmap(*pix); + il->setAlignment(Qt::AlignCenter); + g->addWidget(il,0,0); + QLabel * tl = new QLabel(szLabel,this); + g->addWidget(tl,0,1); + } else { + QLabel * tl = new QLabel(szLabel,this); + g->addMultiCellWidget(tl,0,0,0,1); + } + + g->setColStretch(1,1); + + m_bMultiLine = bMultiLine; + + if(m_bMultiLine) + { + m_pEdit = new QMultiLineEdit(this); + ((QMultiLineEdit *)m_pEdit)->setText(szDefaultText); + } else { + m_pEdit = new QLineEdit(this); + ((QLineEdit *)m_pEdit)->setText(szDefaultText); + } + + g->addMultiCellWidget(m_pEdit,1,1,0,1); + + KviTalHBox * box = new KviTalHBox(this); + g->addMultiCellWidget(box,2,2,0,1); + + m_iEscapeButton = 0; + m_iDefaultButton = 0; + + if(!szButton0.isEmpty()) + { + QString szB = szButton0; + bool bDef = false; + if(KviQString::equalCIN(szB,"default=",8)) + { + bDef = true; + szB.remove(0,8); + m_iDefaultButton = 0; + } else if(KviQString::equalCIN(szB,"escape=",7)) + { + szB.remove(0,7); + m_iEscapeButton = 0; + } + QPushButton * pb1 = new QPushButton(szB,box); + if(bDef)pb1->setDefault(true); + connect(pb1,SIGNAL(clicked()),this,SLOT(b0Clicked())); + } + + if(!szButton1.isEmpty()) + { + QString szB = szButton1; + bool bDef = false; + if(KviQString::equalCIN(szB,"default=",8)) + { + bDef = true; + szB.remove(0,8); + m_iDefaultButton = 1; + } else if(KviQString::equalCIN(szB,"escape=",7)) + { + szB.remove(0,7); + m_iEscapeButton = 1; + } + QPushButton * pb2 = new QPushButton(szB,box); + if(bDef)pb2->setDefault(true); + connect(pb2,SIGNAL(clicked()),this,SLOT(b1Clicked())); + } + + if(!szButton2.isEmpty()) + { + QString szB = szButton2; + bool bDef = false; + if(KviQString::equalCIN(szB,"default=",8)) + { + bDef = true; + szB.remove(0,8); + m_iDefaultButton = 2; + } else if(KviQString::equalCIN(szB,"escape=",7)) + { + szB.remove(0,7); + m_iEscapeButton = 2; + } + QPushButton * pb3 = new QPushButton(szB,box); + if(bDef)pb3->setDefault(true); + connect(pb3,SIGNAL(clicked()),this,SLOT(b2Clicked())); + } + +} + +KviKvsCallbackTextInput::~KviKvsCallbackTextInput() +{ + g_pDialogModuleDialogList->removeRef(this); +} + +void KviKvsCallbackTextInput::b0Clicked() +{ + done(0+10); +} + +void KviKvsCallbackTextInput::b1Clicked() +{ + done(1+10); +} + +void KviKvsCallbackTextInput::b2Clicked() +{ + done(2+10); +} + +void KviKvsCallbackTextInput::closeEvent(QCloseEvent *e) +{ + e->ignore(); + done(m_iEscapeButton+10); +} + +void KviKvsCallbackTextInput::done(int code) +{ + if(code >= 10) + { + code -= 10; + } else { + switch(code) + { + case QDialog::Accepted: + code = m_iDefaultButton; + break; + default: + code = m_iEscapeButton; + break; + } + } + + QString txt; + + if(m_bMultiLine) + { + txt = ((QMultiLineEdit *)m_pEdit)->text(); + } else { + txt = ((QLineEdit *)m_pEdit)->text(); + } + + KviKvsVariantList params; + params.append(new KviKvsVariant((kvs_int_t)code)); + params.append(new KviKvsVariant(txt)); + + execute(¶ms); + + //QDialog::done(code); + + delete this; +} + +void KviKvsCallbackTextInput::showEvent(QShowEvent *e) +{ + move((g_pApp->desktop()->width() - width())/2,(g_pApp->desktop()->height() - height()) / 2); + QDialog::showEvent(e); +} + + + +/* + @doc: dialog.textinput + @type: + command + @title: + dialog.textinput + @short: + Shows a dialog that accepts user input as text + @syntax: + dialog.textinput [-d=<default text>] [-i=<icon>] [-m] [-b] (<caption>,<info_text>,<button0>[,<button1>[,<button2>[,<magic1>[,<magic2>[...]]]]]) + { + <callback_command> + } + @switches: + !sw: -d=<default_text> | --default=<default_text> + Set the initial text input value to <default_text> + !sw: -i=<icon> | --icon=<icon> + Display the specified icon, just of the left of the informational text + !sw: -m | --multiline + Input multiline text instead of single line + @description: + Shows a text input dialog box with the specified <caption> , <info_text> , <icon> and + buttons.[br] + <caption> is a text string that will appear in the caption of the dialog box.[br] + <info_text> is a fixed text string that will appear in the dialog box and can contain HTML formatting.[br] + <button0> is the text of the first button (on the left).[br] + <button1> is the text of the second button (if empty or not given at all, only one button will appear in the dialog).[br] + <button2> is the text of the third button (if empty or not given, only two buttons will appear in the dialog).[br] + If one of the text strings starts with a "default=" prefix then the button is assumed + to be the default button of the dialog and will be also activated when the user presses enter. + If the -m switch is used , the dialog will be a multi-line text input, otherwise the user will be able to + input only a single line of text.[br] + If the -d switch is used , the initial text input value is set to <default text>.[br] + If the -i switch is used , the dialog displays also the icon <icon> , just on the left ot the <info_text>[br] + If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour: + it will appear above its parent widget and block its input until it's closed.[br] + In that case <icon> is an [doc:image_id]image identifier[/doc] (can be a relative or absolute + path to an image file or a signed number (in that case it defines an internal KVIrc image).[br] + <magic1>,<magic2>... are the magic parameters: evaluated at dialog.textinput call time and passed + to the <callback_command> as positional parameters.[br] + Once the dialog has been shown , the user will click one of the buttons. At this point the dialog + is hidden and the <callback_command> is executed passing the text input value in $1, the number of the button clicked + as $0, and the magic parameters as positional parameters $2 , $3 , $4....[br] + Please note that if the user closes the window with the window manager close button , + the action is interpreted as a button2 click (that is usually sth as "Cancel").[br] + @examples: + [example] + [comment]# We need a single line "reason"[/comment] + dialog.textinput -d="Working !" (Away,<center>Please enter the <h1>away message</h1></center>,"Ok","Cancel") + { + switch($0) + { + case(0): + away $1- + break; + default: + # Cancelled + break; + } + } + [/example] +*/ + +static bool dialog_kvs_cmd_textinput(KviKvsModuleCallbackCommandCall * c) +{ + QString szCaption,szInfoText,szIcon,szDefaultText,szButton0,szButton1,szButton2; + KviKvsVariantList params; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption) + KVSM_PARAMETER("info_text",KVS_PT_STRING,0,szInfoText) + KVSM_PARAMETER("button0",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton0) + KVSM_PARAMETER("button1",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton1) + KVSM_PARAMETER("button2",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton2) + KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params) + KVSM_PARAMETERS_END(c) + + QString szCmd = c->callback()->code(); + + c->switches()->getAsStringIfExisting('i',"icon",szIcon); + c->switches()->getAsStringIfExisting('d',"default",szDefaultText); + bool modal; + if(c->hasSwitch('b',"modal")) modal=true; + else modal=false; + KviKvsCallbackTextInput * box = new KviKvsCallbackTextInput( + szCaption,szInfoText,szDefaultText,szIcon,c->switches()->find('m',"multiline"), + szButton0,szButton1,szButton2,szCmd,¶ms,c->window(),modal); + box->show(); + + return true; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +// New KVS +KviKvsCallbackFileDialog::KviKvsCallbackFileDialog( + const QString &szCaption, + const QString &szInitialSelection, + const QString &szFilter, + const QString &szCode, + KviKvsVariantList * pMagicParams, + KviWindow * pWindow,bool modal) + : KviFileDialog(szInitialSelection,szFilter,0,0,modal), KviKvsCallbackObject("dialog.file",pWindow,szCode,pMagicParams,0) +{ + g_pDialogModuleDialogList->append(this); + setCaption(szCaption); +} + +KviKvsCallbackFileDialog::~KviKvsCallbackFileDialog() +{ + g_pDialogModuleDialogList->removeRef(this); +} + +void KviKvsCallbackFileDialog::done(int code) +{ + KviFileDialog::done(code); + KviKvsVariantList params; + + if(code == QDialog::Accepted) + { +#ifdef COMPILE_KDE_SUPPORT + if(mode() == KFile::ExistingOnly) +#else + if(mode() == QFileDialog::ExistingFiles) +#endif + { + KviKvsArray * a = new KviKvsArray(); + QStringList sl = selectedFiles(); + int idx = 0; + for(QStringList::Iterator it = sl.begin();it != sl.end();++it) + { + a->set(idx,new KviKvsVariant(*it)); + idx++; + } + params.append(new KviKvsVariant(a)); + } else { + params.append(new KviKvsVariant(selectedFile())); + } + } else { + params.append(new KviKvsVariant(QString(""))); + } + + hide(); // ensure we're hidden + + // ugly workaround for the Qt filedialog "destructive accept() before this reference" bug + // we can't delete ourselves in this moment.... :((( + // ...so skip out of this call stack and ask KviApp to destroy us just + // when the control returns to the main loop. + // If the module is unloaded then , KviApp will notice it and will NOT delete the dialog + g_pApp->collectGarbage(this); + + // calling dialog.unload here WILL lead to a sigsegv (this is SURE + // with a lot of qt versions that have the ugly file dialog "accept before this reference" bug) + // to avoid it, we can execute the callback triggered by a timer... + // ... umpf ... + execute(¶ms); +} + +/* + @doc: dialog.file + @type: + command + @title: + dialog.file + @short: + Shows a file dialog + @syntax: + dialog.file [-b] (<mode>,<caption>[,<initial_selection[,<file_filter>[,<magic1>[,<magic2>[...]]]]]]) + { + <callback_command> + } + @description: + Shows an openfile dialog box with the specified <caption> , <initial_selection> , and <file_filter>.[br] + <mode> can be "open" , "openm" , "save" or "dir":[br] + "open" causes the dialog to return an existing file[br] + "openm" is similar to open but allows returning multiple files as a comma separated list[br] + "save" causes the dialog to return any file name (no overwrite confirmation is built in the dialog!)[br] + "dir" causes the dialog to return an existing directory name[br] + <mode> defaults to "open".[br] + <caption> is a text string that will appear in the caption of the dialog box.[br] + <initial_selection> can be a directory or filename that will be initially selected in the dialog.[br] + Only files matching <file_filter> are selectable. If filter is an empty string, all files are selectable.[br] + In the filter string multiple filters can be specified separated by either two semicolons next to each + other or separated by newlines. To add two filters, one to show all C++ files and one to show all + header files, the filter string could look like "C++ Files (*.cpp *.cc *.C *.cxx *.c++);;Header Files (*.h *.hxx *.h++)" + <magic1>,<magic2>... are the magic parameters: evaluated at dialog.message call time and passed + to the <callback_command> as positional parameters.[br] + If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour: + it will appear above its parent widget and block its input until it's closed.[br] + Once the dialog has been shown , the user will select an EXISTING file and click either + Ok or Cancel. At this point the dialog is hidden and the <callback_command> is executed passing the selected file(s) as $0 + and the magic parameters as positional parameters $1 , $2 , $3....[br] + If the user clicks "Cancel" or does not select any file the positional parameter $0 will be empty.[br] + @examples: + [example] + dialog.file(open,Choose an audio file,/home/pragma/TheAudio.au,"Audio files (*.au *.wav *.snd)") + { + if("$0" != "")run play $0 + } + [/example] +*/ + +//#warning "Examples for these dialogs!" + + +static bool dialog_kvs_cmd_file(KviKvsModuleCallbackCommandCall * c) +{ + QString szMode,szCaption,szInitialSelection,szFilter; + KviKvsVariantList params; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("mode",KVS_PT_STRING,0,szMode) + KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption) + KVSM_PARAMETER("initial_selection",KVS_PT_STRING,KVS_PF_OPTIONAL,szInitialSelection) + KVSM_PARAMETER("filter",KVS_PT_STRING,KVS_PF_OPTIONAL,szFilter) + KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params) + KVSM_PARAMETERS_END(c) + bool modal; + if(c->hasSwitch('b',"modal")) modal=true; + else modal=false; + QString szCmd = c->callback()->code(); + + KviKvsCallbackFileDialog * box = new KviKvsCallbackFileDialog(szCaption,szInitialSelection,szFilter,szCmd,¶ms,c->window(),modal); + + KviFileDialog::FileMode md = KviFileDialog::ExistingFile; + + if(KviQString::equalCI(szMode,"openm"))md = KviFileDialog::ExistingFiles; + else if(KviQString::equalCI(szMode,"save"))md = KviFileDialog::AnyFile; + else if(KviQString::equalCI(szMode,"dir"))md = KviFileDialog::DirectoryOnly; + + box->setFileMode(md); + + box->show(); + + return true; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +// New KVS +KviKvsCallbackImageDialog::KviKvsCallbackImageDialog( + const QString &szCaption, + const QString &szInitialSelection, + int iType, + int iMaxSize, + const QString &szCode, + KviKvsVariantList * pMagicParams, + KviWindow * pWindow,bool modal) + : KviImageDialog(0,szCaption,iType,0,szInitialSelection,iMaxSize,modal), KviKvsCallbackObject("dialog.image",pWindow,szCode,pMagicParams,0) +{ + g_pDialogModuleDialogList->append(this); +} + +KviKvsCallbackImageDialog::~KviKvsCallbackImageDialog() +{ + g_pDialogModuleDialogList->removeRef(this); +} + +void KviKvsCallbackImageDialog::done(int code) +{ + KviImageDialog::done(code); + KviKvsVariantList params; + + if(code == QDialog::Accepted) + { + params.append(new KviKvsVariant(selectedImage())); + } else { + params.append(new KviKvsVariant(QString(""))); + } + + hide(); // ensure we're hidden + + // ugly workaround for the Qt filedialog "destructive accept() before this reference" bug + // we can't delete ourselves in this moment.... :((( + // ...so skip out of this call stack and ask KviApp to destroy us just + // when the control returns to the main loop. + // If the module is unloaded then , KviApp will notice it and will NOT delete the dialog + g_pApp->collectGarbage(this); + + // calling dialog.unload here WILL lead to a sigsegv (this is SURE + // with a lot of qt versions that have the ugly file dialog "accept before this reference" bug) + // to avoid it, we can execute the callback triggered by a timer... + // ... umpf ... + execute(¶ms); +} + + +/* + @doc: dialog.image + @type: + command + @title: + dialog.image + @short: + Shows a image dialog + @syntax: + dialog.image [-b] (<type>,<caption>,<initial_directory>,[<maxsize>,[,<magic1>[,<magic2>[...]]]]]]) + { + <callback_command> + } + @description: + Shows a dialog that allows selecting an [doc:image_id]image_id[doc]. + The <type> parameter must be a combination of the following flags:<br> + 's' : allow selecting from the KVIrc builtin small icons<br> + 'f' : allow browsing the local directories<br> + 'a' : all of the above<br> + The default for <type> is 'a'.<br> + <caption> is the caption string for the dialog.<br> + <initial_directory> makes sense only if 'f' is specified (if <initial_directory> is empty + then the last path used by the image dialog will be used).<br> + <maxsize> is the maximum size of the images for that the preview will be generated: + this is 256000 bytes by default (if unspecified). Don't make it a lot bigger : it can take a lot to make + the thumbnails for bigger images (and it can eat a considerable amount of memory).<br> + <magic1>,<magic2>... are the magic parameters: evaluated at dialog.image call time and passed + to the <callback_command> as positional parameters.[br] + If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour: + it will appear above its parent widget and block its input until it's closed.[br] + Once the dialog has been shown , the user will select an EXISTING file and click either + Ok or Cancel. At this point the dialog is hidden and the <callback_command> is executed passing the selected file(s) as $0 + and the magic parameters as positional parameters $1 , $2 , $3....[br] + If the user clicks "Cancel" or does not select any image the positional parameter $0 will be empty.[br] + @examples: + [example] + dialog.image(f,Choose an image file,/home/pragma/,"256000") + { + if("$0" != "")run kview $0 + } + [/example] +*/ + +//#warning "Examples for these dialogs!" + + +static bool dialog_kvs_cmd_image(KviKvsModuleCallbackCommandCall * c) +{ + QString szType,szCaption,szInitialSelection; + kvs_uint_t iMaxSize; + KviKvsVariantList params; + + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("mode",KVS_PT_STRING,0,szType) + KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption) + KVSM_PARAMETER("initial_directory",KVS_PT_STRING,0,szInitialSelection) + KVSM_PARAMETER("maxsize",KVS_PT_UINT,KVS_PF_OPTIONAL,iMaxSize) + KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params) + KVSM_PARAMETERS_END(c) + bool modal; + if(c->hasSwitch('b',"modal")) modal=true; + else modal=false; + QString szCmd = c->callback()->code(); + + int iType = 0; + + if(szType.contains('s'))iType |= KID_TYPE_BUILTIN_IMAGES_SMALL; + if(szType.contains('f'))iType |= KID_TYPE_FULL_PATH; + if(szType.isEmpty())iType = KID_TYPE_ALL; + + if(iMaxSize < 1)iMaxSize = 256000; + + KviKvsCallbackImageDialog * box = new KviKvsCallbackImageDialog(szCaption,szInitialSelection,iType,iMaxSize,szCmd,¶ms,c->window(),modal); + + box->show(); + + return true; +} + +/* + @doc: dialog.yesno + @type: + function + @title: + $dialog.yesno + @short: + Shows a simple yes/no dialog + @syntax: + $dialog.yesno(<caption:string>,<szText:string>) + @description: + Shows a simple yes/no dialog. Returns 1 if user clicks "Yes" and 0 if (s)he clicks "No". + Please note that this dialog is BLOCKING: it blocks execution of the script + until the user has selected either YES or NO. + @examples: + @seealso: +*/ + +static bool dialog_kvs_fnc_yesno(KviKvsModuleFunctionCall * c) +{ + QString szCaption; + QString szText; + KVSM_PARAMETERS_BEGIN(c) + KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption) + KVSM_PARAMETER("text",KVS_PT_STRING,0,szText) + KVSM_PARAMETERS_END(c) + + c->enterBlockingSection(); + bool yes=KviMessageBox::yesNo(szCaption,szText); // this will happily crash on quit ? + if(!c->leaveBlockingSection())return true; // just die + c->returnValue()->setBoolean(yes); + return true; +} + +/* + +static int g_iLocalEventLoops = 0; + +static bool dialog_module_cmd_unload(KviModule *m,KviCommand *c) +{ + // We use local loops in this module: we must FORBID explicit unloading of the + // module while local even loops are running + ENTER_STACK_FRAME(c,"dialog_module_cmd_unload"); + c->warning(__tr("The dialog module can't be explicitly unloaded: a modal dialog is currently open")); + return c->leaveStackFrame(); +} + +static void dialog_module_entering_local_loop(KviModule * m) +{ + // Replace unload + g_iLocalEventLoops++; + if(g_iLocalEventLoops == 1)m->registerCommand("unload",dialog_module_cmd_unload); +} + +static void dialog_module_exiting_local_loop(KviModule * m) +{ + g_pModuleManager->registerDefaultCommands(m); + g_iLocalEventLoops--; +} + +static bool dialog_module_fnc_textline(KviModule *m,KviCommand *c,KviParameterList * parms,KviStr &buffer) +{ + ENTER_STACK_FRAME(c,"dialog_module_fnc_textline"); + + KviStr caption = parms->safeFirstParam(); + KviStr info = parms->safeNextParam(); + KviStr initial = parms->safeNextParam(); + + dialog_module_entering_local_loop(m); + QMessageBox::information(0,caption.ptr(),info.ptr(),QMessageBox::Ok); + dialog_module_exiting_local_loop(m); + + // It might be that the current window is no longer available!!! + + return c->leaveStackFrame(); +} + +*/ + +/* + @doc: noblockingdialogs + @type: + generic + @title: + Why there are no blocking dialogs in KVIrc ? + @short: + Tecnical answer + @description: + Why there are no blocking dialogs in KVIrc ?[br] + The answer is simple: because they're more confusing and tricky than it seems.[br] + Blocking the entire program control flow while showing a dialog is + rather a bad idea since we have to deal with external entities (servers and other users) + that are NOT blocked. This means that the blocking dialogs must block only the + script control-flow but let the rest of the application running. + Such blocking dialogs actually seem to simplify scripting because + the programmer "feels" that the control is always left in the script snippet that he is writing. + This is actually confusing: the control IS in the script snippet but while the dialog + is open the whole world can change: you can return from the dialog call and discover + that the server connection no longer exists and the application is about to quit.[br] + This may happen even with non-blocking dialogs ,but in non-blocking mode you have + a way to handle this event. Consider the following snippet of code:[br] + [example] + echo My name is $? + [/example] + Where $? stands for a blocking input dialog that asks the user for some text.[br] + When the input dialog returns the window that the echo was directed to no longer + exists and you have no way to stop the echo! (Well...I could add extra code + in the executable to handle all these situations but that would be really too expensive).[br] + With object scripting this is actually dangerous: you might use a blocking dialog + in an object signal handler and when returning discover that this object has been deleted! + (The example refers to a simple object , but think about a complex hierarchy of objects + where one random gets deleted...).[br] + This is why the dialogs in KVIrc are non-blocking :)[br] + That's REAL programming. +*/ + + + + + + + +static bool dialog_module_init(KviModule * m) +{ + g_pDialogModuleDialogList = new KviPointerList<QWidget>; + g_pDialogModuleDialogList->setAutoDelete(false); + + KVSM_REGISTER_CALLBACK_COMMAND(m,"message",dialog_kvs_cmd_message); + KVSM_REGISTER_CALLBACK_COMMAND(m,"textinput",dialog_kvs_cmd_textinput); + KVSM_REGISTER_CALLBACK_COMMAND(m,"file",dialog_kvs_cmd_file); + KVSM_REGISTER_CALLBACK_COMMAND(m,"image",dialog_kvs_cmd_image); + + KVSM_REGISTER_FUNCTION(m,"yesno",dialog_kvs_fnc_yesno); + + return true; +} + +static bool dialog_module_cleanup(KviModule *m) +{ + // Here we get a tragedy if g_iLocalEventLoops > 0! + while(g_pDialogModuleDialogList->first())delete g_pDialogModuleDialogList->first(); + delete g_pDialogModuleDialogList; + g_pDialogModuleDialogList = 0; + return true; +} + +static bool dialog_module_can_unload(KviModule *m) +{ + return g_pDialogModuleDialogList->isEmpty(); +} + + +KVIRC_MODULE( + "KVIrc script dialogs", + "1.0.0", + "Szymon Stefanek <pragma at kvirc dot net>" , + "Adds the /dialog.* commands functionality\n", + dialog_module_init , + dialog_module_can_unload, + 0, + dialog_module_cleanup +) + +#include "libkvidialog.moc" |