30 #include <QApplication> 31 #include <QCloseEvent> 32 #include <QCommandLineParser> 33 #include <QDesktopWidget> 37 #include <QLatin1Char> 40 #include <QMdiSubWindow> 42 #include <QMutableMapIterator> 44 #include <QSizePolicy> 46 #include <QStringList> 51 #include <KConfigGroup> 53 #include <KLocalizedString> 54 #include <KMessageBox> 55 #include <KSharedConfig> 86 #define CASE_COMMAND(x) } else if (parser.command() == _(x)) { 89 #define TOOLBAR_FILE _("MainWidget File") 92 #define TOOLBAR_EDIT _("MainWidget Edit") 95 #define TOOLBAR_RECORD_PLAY _("MainWidget Record/Playback") 98 #define TOOLBAR_ZOOM _("MainWidget Zoom") 106 m_toolbar_record_playback(Q_NULLPTR),
107 m_toolbar_zoom(Q_NULLPTR),
108 m_menu_manager(Q_NULLPTR),
109 m_mdi_area(Q_NULLPTR),
110 m_action_save(Q_NULLPTR),
111 m_action_save_as(Q_NULLPTR),
112 m_action_close(Q_NULLPTR),
113 m_action_undo(Q_NULLPTR),
114 m_action_redo(Q_NULLPTR),
115 m_action_cut(Q_NULLPTR),
116 m_action_copy(Q_NULLPTR),
117 m_action_erase(Q_NULLPTR),
118 m_action_delete(Q_NULLPTR),
119 m_lbl_status_size(Q_NULLPTR),
120 m_lbl_status_mode(Q_NULLPTR),
121 m_lbl_status_cursor(Q_NULLPTR)
124 QStatusBar *status_bar = statusBar();
125 Q_ASSERT(status_bar);
126 if (!status_bar)
return;
128 QLabel *spacer =
new QLabel(
this);
129 const int frame_style = QFrame::StyledPanel | QFrame::Sunken;
130 status_bar->addWidget(spacer);
131 spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
132 spacer->setFrameStyle(frame_style);
133 QSizePolicy policy = spacer->sizePolicy();
134 policy.setHorizontalStretch(100);
135 spacer->setSizePolicy(policy);
136 policy.setHorizontalStretch(0);
155 bool iconic = (args && args->isSet(
_(
"iconic")));
160 setAcceptDrops(
true);
163 setFocusPolicy(Qt::WheelFocus);
176 connect(context, SIGNAL(sigUndoRedoInfo(QString,QString)),
178 connect(context, SIGNAL(sigModified()),
198 connect(context, SIGNAL(sigStatusBarMessage(QString,uint)),
210 if (!context)
return Q_NULLPTR;
211 if (!context->
init(
this)) {
246 QMdiSubWindow *current_sub =
m_mdi_area->currentSubWindow();
248 qWarning(
"WARNING: unassociated MDI sub window %p?",
249 static_cast<void *>(current_sub));
250 QMapIterator<QMdiSubWindow*, Kwave::FileContext*> it(
m_context_map);
252 while (it.hasNext()) {
254 context = it.value();
261 Q_ASSERT(0 &&
"SDI mode but no context?");
270 QMenuBar *menubar = menuBar();
272 if (!menubar)
return false;
306 if (!context)
return false;
308 QWidget *central_widget = Q_NULLPTR;
318 m_mdi_area =
new(std::nothrow) QMdiArea(
this);
321 m_mdi_area->setViewMode(QMdiArea::SubWindowView);
325 m_mdi_area =
new(std::nothrow) QMdiArea(
this);
328 m_mdi_area->setViewMode(QMdiArea::TabbedView);
344 Q_ASSERT(toolbar_file);
345 if (!toolbar_file)
return false;
349 toolbar_file->addAction(
350 QIcon::fromTheme(
_(
"document-new")),
351 i18n(
"Create a new empty file"),
354 toolbar_file->addAction(
355 QIcon::fromTheme(
_(
"document-open")),
356 i18n(
"Open an existing file"),
360 QIcon::fromTheme(
_(
"document-save")),
361 i18n(
"Save the current file"),
365 QIcon::fromTheme(
_(
"document-save-as")),
366 i18n(
"Save the current file under a different name or file format..."),
370 QIcon::fromTheme(
_(
"document-close")),
371 i18n(
"Close the current file"),
377 Q_ASSERT(toolbar_edit);
378 if (!toolbar_edit)
return false;
381 QIcon::fromTheme(
_(
"edit-undo")),
386 QIcon::fromTheme(
_(
"edit-redo")),
391 QIcon::fromTheme(
_(
"edit-cut")),
396 QIcon::fromTheme(
_(
"edit-copy")),
400 QAction *btPaste = toolbar_edit->addAction(
401 QIcon::fromTheme(
_(
"edit-paste")),
406 btPaste, SLOT(setEnabled(
bool)));
409 QIcon::fromTheme(
_(
"draw-eraser")),
410 i18n(
"Mute selection"),
414 QIcon::fromTheme(
_(
"edit-delete")),
415 i18n(
"Delete selection"),
419 Q_ASSERT(central_widget);
423 setCentralWidget(central_widget);
426 int w = central_widget->minimumSize().width();
427 w = qMax(w, central_widget->sizeHint().width());
428 w = qMax(w, width());
429 int h = qMax(central_widget->sizeHint().height(), (w * 6) / 10);
430 h = qMax(h, height());
441 QRect desk = qApp->desktop()->rect();
442 QRect g = this->geometry();
443 if (!desk.contains(g)) {
448 g = desk.intersected(g);
453 setAutoSaveSettings();
457 KConfigGroup cfg = KSharedConfig::openConfig()->group(
"MainWindow");
458 QString magic =
_(
"3");
459 if (cfg.readEntry(
"toolbars") != magic) {
460 qDebug(
"toolbar layout changed => resetting toolbars to defaults");
463 KToolBar::setToolBarsLocked(
false);
468 cfg.writeEntry(
"toolbars", magic);
497 if (context)
delete context;
506 QList<Kwave::App::FileAndInstance> all_files;
509 if (!context)
continue;
511 if (!name.length())
continue;
522 QList<Kwave::FileContext *> list;
524 QMutableMapIterator<QMdiSubWindow *, Kwave::FileContext *> i(
m_context_map);
525 while (i.hasNext()) {
527 QMdiSubWindow *sub = i.key();
535 Qt::WindowStates state = sub->windowState();
536 if (state & Qt::WindowMinimized)
538 state &= ~Qt::WindowMinimized;
539 sub->setWindowState(state);
544 sub->setWidget(Q_NULLPTR);
550 context->disconnect();
560 setCentralWidget(Q_NULLPTR);
578 if (!context)
return;
608 m_mdi_area =
new(std::nothrow) QMdiArea(
this);
611 m_mdi_area->setViewMode(QMdiArea::SubWindowView);
617 m_mdi_area =
new(std::nothrow) QMdiArea(
this);
620 m_mdi_area->setViewMode(QMdiArea::TabbedView);
633 QMdiSubWindow *sub =
m_mdi_area->addSubWindow(
634 main_widget, Qt::SubWindow);
645 connect(sub, SIGNAL(destroyed(QObject*)),
656 QMenu *m = sub->systemMenu();
658 foreach (QAction *act, m->actions())
659 if (act) act->setShortcut(0);
663 sub->setAttribute(Qt::WA_DeleteOnClose);
670 Qt::WindowStates state = sub->windowState();
673 state |= Qt::WindowMaximized;
674 sub->setWindowState(state);
679 state &= ~Qt::WindowMaximized;
680 sub->setWindowState(state);
686 sub->setHidden(
false);
709 QString command = line;
712 if (!command.length())
return 0;
727 KHelpMenu *dlg =
new KHelpMenu(
this,
_(
"Kwave"));
728 if (dlg) dlg->aboutKDE();
736 unsigned int bits = parser.
toUInt();
737 unsigned int tracks = parser.
toUInt();
738 result =
newSignal(samples, rate, bits, tracks);
741 if (!filename.isEmpty()) {
743 result =
loadFile(QUrl::fromUserInput(filename));
751 result = (close()) ? 0 : -1;
754 i18n(
"Reset the toolbar to default settings?"))
755 == KMessageBox::Yes) ? 1 : 0))
764 if (gui_type ==
_(
"SDI"))
766 else if (gui_type ==
_(
"MDI"))
768 else if (gui_type ==
_(
"TAB"))
773 KConfigGroup cfg = KSharedConfig::openConfig()->group(
"Global");
774 cfg.writeEntry(
_(
"UI Type"), gui_type);
779 i18n(
"Re-enable all disabled notifications?\n" 780 "All messages that you previously turned off by activating " 781 "the \"Do not ask again\" checkbox will then be enabled again." 783 == KMessageBox::Yes) ? 1 : 0))
785 KMessageBox::enableAllMessages();
792 QMdiSubWindow *sub =
m_mdi_area->activeSubWindow();
794 sub->setWindowState(windowState() | Qt::WindowMinimized);
798 setWindowState(windowState() | Qt::WindowMinimized);
818 foreach (QMdiSubWindow *sub,
m_mdi_area->subWindowList()) {
819 if (sub && !(sub->windowState() & Qt::WindowMinimized))
822 if (!count)
return 0;
826 int height = total_height / count;
827 int increment = height;
829 foreach (QMdiSubWindow *sub,
m_mdi_area->subWindowList()) {
830 if (!sub || (sub->windowState() & Qt::WindowMinimized))
833 sub->resize(width, height);
845 if (!context)
continue;
854 Qt::WindowStates state = sub->windowState();
855 if (state & Qt::WindowMinimized)
856 sub->setWindowState(state & ~(Qt::WindowMinimized));
861 }
else return ENOSYS;
874 if (!context)
return EAGAIN;
881 if (plugin_manager) plugin_manager->
sync();
891 QMutableMapIterator<QMdiSubWindow *, Kwave::FileContext *>
894 while (it.hasPrevious()) {
896 QMdiSubWindow *sub = it.key();
902 if (context) allowed &= context->
closeFile();
939 if ( signal_manager && !signal_manager->
isEmpty() &&
944 if (context && !context->
closeFile())
return -1;
954 if (context && context->
isEmpty()) {
976 if (!context)
return -1;
980 m_mdi_area->geometry().size() * 0.85))
return -1;
999 _(
"CMD: from command line: '") + cmd +
_(
"'"));
1004 if (!context)
return -1;
1006 Q_ASSERT(signal_manager);
1010 url.toLocalFile() : url.toDisplayString());
1013 if (!url.isLocalFile())
return -1;
1016 QFileInfo file(url.fileName());
1017 QString suffix = file.suffix();
1018 if (suffix ==
_(
"kwave")) {
1020 i18n(
"Executing Kwave script file '%1'...", url.toDisplayString())
1027 if ((retval <= 0) || !context)
return retval;
1030 i18n(
"Loading file '%1'...", url.toDisplayString())
1037 if (signal_manager && !(res = signal_manager->
loadFile(url))) {
1040 qWarning(
"TopWidget::loadFile() failed: result=%d", res);
1044 reason = i18n(
"Out of memory");
1047 reason = i18nc(
"error message after opening a file failed",
1048 "Unable to open '%1'", url.toDisplayString());
1051 reason = i18nc(
"error message after opening a file failed",
1052 "Invalid or unknown file type: '%1'",
1053 url.toDisplayString());
1060 if (reason.length()) {
1086 _(
"kfiledialog:///kwave_open_dir"),
1089 if (!dlg)
return -1;
1090 dlg->setWindowTitle(i18n(
"Open"));
1091 if (dlg->exec() == QDialog::Accepted) {
1103 unsigned int bits,
unsigned int tracks)
1106 if (!context)
return -1;
1109 if (!signal_manager)
return -1;
1112 _(
"newsignal(%1,%2,%3,%4)" 1113 ).arg(samples).arg(rate).arg(bits).arg(tracks));
1115 if (retval <= 0)
return retval;
1118 if (!signal_manager)
return -1;
1120 signal_manager->
newSignal(samples, rate, bits, tracks);
1127 Q_ASSERT(statusBar());
1133 unsigned int tracks = info.
tracks();
1134 double rate = info.
rate();
1135 unsigned int bits = info.
bits();
1139 double ms = (rate > 0) ? (static_cast<double>(length) /
1140 static_cast<double>(rate) * 1E3) : 0;
1141 txt =
_(
" ") + i18nc(
1142 "Length, as in total duration of loaded song",
1143 "Length: %1 (%2 samples)",
1152 QString khz =
_(
"%0.3f");
1153 khz = khz.sprintf(
"%0.3f", static_cast<double>(rate) * 1E-3);
1154 txt =
_(
" ") + i18n(
"Mode: %1 kHz @ %2 Bit", khz, bits) +
_(
" ");
1159 bool have_signal = (tracks != 0);
1177 if (!context)
return;
1180 Q_ASSERT(signal_manager);
1181 if (!signal_manager)
return;
1182 Q_ASSERT(statusBar());
1183 if (!statusBar())
return;
1186 const double rate = signal_manager->
rate();
1187 const bool sample_mode = (qFuzzyIsNull(rate));
1195 QString txt =
_(
" ");
1198 "%1=first sample, %2=last sample, %3=number of samples, "\
1199 "example: 'Selected: 2000...3000 (1000 samples)'",
1200 "Selected: %1...%2 (%3 samples)",
1206 double ms_first =
static_cast<double>(offset) * 1E3 / rate;
1207 double ms_last =
static_cast<double>(last + 1) * 1E3 / rate;
1208 double ms = (ms_last - ms_first);
1210 "%1=start time, %2=end time, %3=time span, "\
1211 "example: 'Selected: 02:00...05:00 (3 min)'",
1212 "Selected: %1...%2 (%3)",
1220 statusBar()->showMessage(txt, 4000);
1227 if (sample_mode || !signal_manager->
tracks()) {
1230 double ms_first =
static_cast<double>(offset) * 1E3 / rate;
1231 QString txt = i18n(
"Position: %1",
1247 const QString &redo)
1250 bool undo_enabled = (undo.length() != 0);
1251 bool redo_enabled = (redo.length() != 0);
1255 txt = (undo_enabled) ?
1256 i18nc(
"tooltip of the undo toolbar button if undo enabled",
1257 "Undo (%1)", undo) :
1258 i18nc(
"tooltip of the undo toolbar button if undo disabled",
1266 txt = (redo_enabled) ?
1267 i18nc(
"tooltip of the redo toolbar button, redo enabled",
1268 "Redo (%1)", redo) :
1269 i18nc(
"tooltip of the redo toolbar button, redo disabled",
1279 txt = (undo_enabled) ?
1280 i18nc(
"menu entry for undo if undo enabled",
"Undo (%1)", undo) :
1281 i18nc(
"menu entry for undo if undo disabled",
"Undo");
1286 txt = (redo_enabled) ?
1287 i18nc(
"menu entry for redo if redo enabled",
"Redo (%1)", redo) :
1288 i18nc(
"menu entry for redo if redo disabled",
"Redo");
1308 _(
"ID_FILE_OPEN_RECENT"), file, QString());
1324 bool have_window_menu =
false;
1345 have_window_menu =
true;
1356 have_window_menu =
true;
1360 if (have_window_menu) {
1363 unsigned int win_count = 0;
1367 if (!caption.length())
continue;
1369 caption, QString());
1373 bool on = (win_count > 1);
1382 bool have_file = (context && context->
signalName().length());
1387 bool have_labels =
false;
1388 if (signal_manager) {
1390 have_labels = !labels.isEmpty();
1393 if (labels.count()) {
1397 _(
"ID_LABEL_DELETE"),
1398 i18nc(
"special entry in the list of labels to delete all",
1402 unsigned int index = 0;
1405 QString desc = (name.length()) ?
1407 "list menu entry of a label, %1=index, %2=description/name",
1408 "#%1 (%2)", index, name) :
1409 i18nc(
"list menue entry of a label, " 1410 "without description, %1=index",
1413 _(
"ID_LABEL_DELETE"), desc, name.setNum(index));
1421 unsigned int tracks = (signal_manager) ? signal_manager->
tracks() : 0;
1424 for (
unsigned int i = 0; i < tracks; i++) {
1426 _(
"ID_EDIT_TRACK_DELETE"), buf.setNum(i), buf.setNum(i));
1430 bool have_signal = (tracks != 0);
1436 bool enable_revert =
false;
1437 if (signal_manager) {
1441 bool is_modified = signal_manager->
isModified();
1442 enable_revert = have_filename && is_modified;
1460 int icon_size_def = style()->pixelMetric(QStyle::PM_ToolBarIconSize);
1461 int icon_size_big = style()->pixelMetric(QStyle::PM_LargeIconSize);
1464 foreach(KToolBar *bar, toolBars()) {
1465 bar->setToolButtonStyle(Qt::ToolButtonIconOnly);
1466 bar->setIconSize( QSize(icon_size_def, icon_size_def) );
1475 insertToolBar(toolbar_zoom, toolbar_record_play);
1476 insertToolBar(toolbar_record_play, toolbar_edit);
1477 insertToolBar(toolbar_edit, toolbar_file);
1480 insertToolBarBreak(toolbar_record_play);
1483 toolbar_record_play->setIconSize(QSize(icon_size_big, icon_size_big));
1484 toolbar_zoom->setIconSize(QSize(icon_size_big, icon_size_big));
1486 foreach(KToolBar *bar, toolBars()) {
1496 if (!context)
return;
1499 Q_ASSERT(signal_manager);
1500 if (!signal_manager)
return;
1502 bool have_signal = signal_manager->
tracks();
1536 QString caption = (context) ? context->
windowCaption(
true) : QString();
1537 setCaption(caption);
1556 QStatusBar *status_bar = statusBar();
1557 if (!status_bar)
return;
1560 status_bar->showMessage(msg, ms);
1562 status_bar->clearMessage();
1575 QMdiSubWindow *sub =
static_cast<QMdiSubWindow *
>(obj);
1583 if (!context)
return;
1600 if ((event->proposedAction() != Qt::MoveAction) &&
1601 (event->proposedAction() != Qt::CopyAction))
1605 event->acceptProposedAction();
1612 if (!event->mimeData())
return;
1614 if (event->mimeData()->hasUrls()) {
1616 foreach (
const QUrl &url, event->mimeData()->urls()) {
1617 QString filename = url.toLocalFile();
sample_index_t toSampleIndex()
int loadFile(const QUrl &url)
int loadBatch(const QUrl &url)
static QString fromUrl(const QUrl &url)
QString Q_DECL_EXPORT ms2string(double ms, int precision=6)
QString Q_DECL_EXPORT samples2string(sample_index_t samples)
static void showMessage(const QString &message)
static ClipBoard & instance()
void setParent(Kwave::TopWidget *top_widget)
Kwave::MetaDataList & metaData()
Kwave::Selection & selection()
void newSignal(sample_index_t samples, double rate, unsigned int bits, unsigned int tracks)
static int questionYesNo(QWidget *widget, QString message, QString caption=QString(), const QString buttonYes=QString(), const QString buttonNo=QString(), const QString &dontAskAgainName=QString())
bool init(Kwave::TopWidget *top_widget)
static QString mimeTypeOf(const QUrl &url)
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
QString windowCaption(bool with_modified) const
sample_index_t length() const
static int error(QWidget *widget, QString message, QString caption=QString())
void switchGuiType(Kwave::TopWidget *top, GuiType new_type)
QString signalName() const
sample_index_t length() const
bool createMainWidget(const QSize &preferred_size)
virtual QString name() const
unsigned int tracks() const
static QUrl toUrl(const QString &command)
static QString decodingFilter()
int newWindow(const QUrl &url)
QWidget * mainWidget() const
const QCommandLineParser * cmdline() const
const QString & firstParam()
static bool canDecode(const QMimeData *source)
QStringList recentFiles() const
QString Q_DECL_EXPORT urlScheme()
QPair< QString, int > FileAndInstance
static void Q_DECL_EXPORT log(const QObject *sender, LogLevel level, const QString &msg)
unsigned int bits() const
Kwave::PluginManager * pluginManager() const
Kwave::SignalManager * signalManager() const
static QString escape(const QString &text)
void addRecentFile(const QString &filename)
int executeCommand(const QString &command)
bool toplevelWindowHasClosed(Kwave::TopWidget *todel)
static bool canDecode(const QString &mimetype_name)
const QString & nextParam()
int executeCommand(const QString &command)