From f8d95bba71fea5266820f7cc8ad863ec809e6db3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 6 Jul 2016 21:30:14 +0300 Subject: [PATCH] Using GTK file dialog when it is available. Should work both with GTK 2 and GTK 3. --- Telegram/SourceFiles/app.h | 2 - Telegram/SourceFiles/mainwindow.cpp | 4 +- .../platform/linux/file_dialog_linux.cpp | 501 +++++++++++ .../platform/linux/file_dialog_linux.h | 145 ++++ .../platform/linux/linux_gdk_helper.cpp | 118 +++ .../platform/linux/linux_gdk_helper.h | 40 + .../SourceFiles/platform/linux/linux_libs.cpp | 118 ++- .../SourceFiles/platform/linux/linux_libs.h | 125 +++ .../platform/platform_file_dialog.h | 61 ++ Telegram/SourceFiles/ui/filedialog.cpp | 45 +- Telegram/SourceFiles/ui/filedialog.h | 10 + Telegram/Telegram.pro | 812 +++++++++--------- Telegram/qt_static.pri | 1 + 13 files changed, 1534 insertions(+), 448 deletions(-) create mode 100644 Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp create mode 100644 Telegram/SourceFiles/platform/linux/file_dialog_linux.h create mode 100644 Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp create mode 100644 Telegram/SourceFiles/platform/linux/linux_gdk_helper.h create mode 100644 Telegram/SourceFiles/platform/platform_file_dialog.h diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h index d2e06ce10..fef9fcbd1 100644 --- a/Telegram/SourceFiles/app.h +++ b/Telegram/SourceFiles/app.h @@ -27,8 +27,6 @@ class MainWindow; class MainWidget; class SettingsWidget; class ApiWrap; -class Font; -class Color; class FileUploader; #include "history.h" diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index cc0020b74..ba495270d 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -505,9 +505,7 @@ void MainWindow::clearWidgets() { intro = 0; } if (_mediaView) { - if (!_mediaView->isHidden()) { - _mediaView->hide(); - } + hideMediaview(); _mediaView->rpcClear(); } title->updateBackButton(); diff --git a/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp b/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp new file mode 100644 index 000000000..9a2577c4e --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/file_dialog_linux.cpp @@ -0,0 +1,501 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "platform/linux/file_dialog_linux.h" + +#include +#include "platform/linux/linux_libs.h" +#include "platform/linux/linux_gdk_helper.h" +#include "mainwindow.h" +#include "localstorage.h" + +QStringList qt_make_filter_list(const QString &filter); + +namespace Platform { +namespace FileDialog { + +using Type = ::FileDialog::internal::Type; + +bool Supported() { + return Platform::internal::GdkHelperLoaded() + && (Libs::gtk_widget_hide_on_delete != nullptr) + && (Libs::gtk_clipboard_store != nullptr) + && (Libs::gtk_clipboard_get != nullptr) + && (Libs::gtk_widget_destroy != nullptr) + && (Libs::gtk_dialog_get_type != nullptr) + && (Libs::gtk_dialog_run != nullptr) + && (Libs::gtk_widget_realize != nullptr) + && (Libs::gdk_window_set_modal_hint != nullptr) + && (Libs::gtk_widget_show != nullptr) + && (Libs::gdk_window_focus != nullptr) + && (Libs::gtk_widget_hide != nullptr) + && (Libs::gtk_widget_hide_on_delete != nullptr) + && (Libs::gtk_file_chooser_dialog_new != nullptr) + && (Libs::gtk_file_chooser_get_type != nullptr) + && (Libs::gtk_file_chooser_set_current_folder != nullptr) + && (Libs::gtk_file_chooser_get_current_folder != nullptr) + && (Libs::gtk_file_chooser_set_current_name != nullptr) + && (Libs::gtk_file_chooser_select_filename != nullptr) + && (Libs::gtk_file_chooser_get_filenames != nullptr) + && (Libs::gtk_file_chooser_set_filter != nullptr) + && (Libs::gtk_file_chooser_get_filter != nullptr) + && (Libs::gtk_window_get_type != nullptr) + && (Libs::gtk_window_set_title != nullptr) + && (Libs::gtk_file_chooser_set_local_only != nullptr) + && (Libs::gtk_file_chooser_set_action != nullptr) + && (Libs::gtk_file_chooser_set_select_multiple != nullptr) + && (Libs::gtk_file_chooser_set_do_overwrite_confirmation != nullptr) + && (Libs::gtk_file_chooser_remove_filter != nullptr) + && (Libs::gtk_file_filter_set_name != nullptr) + && (Libs::gtk_file_filter_add_pattern != nullptr) + && (Libs::gtk_file_chooser_add_filter != nullptr) + && (Libs::gtk_file_filter_new != nullptr); +} + +bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, Type type, QString startFile) { + auto parent = App::wnd() ? App::wnd()->filedialogParent() : nullptr; + internal::GtkFileDialog dialog(parent, caption, QString(), filter); + + dialog.setModal(true); + if (type == Type::ReadFile || type == Type::ReadFiles) { + dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile); + dialog.setAcceptMode(QFileDialog::AcceptOpen); + } else if (type == Type::ReadFolder) { + dialog.setAcceptMode(QFileDialog::AcceptOpen); + dialog.setFileMode(QFileDialog::Directory); + dialog.setOption(QFileDialog::ShowDirsOnly); + } else { + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setAcceptMode(QFileDialog::AcceptSave); + } + if (startFile.isEmpty() || startFile.at(0) != '/') { + startFile = cDialogLastPath() + '/' + startFile; + } + dialog.selectFile(startFile); + + int res = dialog.exec(); + + QString path = dialog.directory().absolutePath(); + if (path != cDialogLastPath()) { + cSetDialogLastPath(path); + Local::writeUserSettings(); + } + + if (res == QDialog::Accepted) { + if (type == Type::ReadFiles) { + files = dialog.selectedFiles(); + } else { + files = dialog.selectedFiles().mid(0, 1); + } + return true; + } + + files = QStringList(); + remoteContent = QByteArray(); + return false; +} + +namespace internal { + +QGtkDialog::QGtkDialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) +{ + g_signal_connect_swapped(G_OBJECT(gtkWidget), "response", G_CALLBACK(onResponse), this); + g_signal_connect(G_OBJECT(gtkWidget), "delete-event", G_CALLBACK(Libs::gtk_widget_hide_on_delete), NULL); +} + +QGtkDialog::~QGtkDialog() +{ + Libs::gtk_clipboard_store(Libs::gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)); + Libs::gtk_widget_destroy(gtkWidget); +} + +GtkDialog *QGtkDialog::gtkDialog() const +{ + return Libs::gtk_dialog_cast(gtkWidget); +} + +void QGtkDialog::exec() { + if (auto w = App::wnd()) { + w->onReActivate(); + QTimer::singleShot(200, w, SLOT(onReActivate())); + } + if (modality() == Qt::ApplicationModal) { + // block input to the whole app, including other GTK dialogs + Libs::gtk_dialog_run(gtkDialog()); + } else { + // block input to the window, allow input to other GTK dialogs + QEventLoop loop; + connect(this, SIGNAL(accept()), &loop, SLOT(quit())); + connect(this, SIGNAL(reject()), &loop, SLOT(quit())); + loop.exec(); + } +} + +void QGtkDialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) { + connect(parent, &QWindow::destroyed, this, &QGtkDialog::onParentWindowDestroyed, + Qt::UniqueConnection); + setParent(parent); + setFlags(flags); + setModality(modality); + + Libs::gtk_widget_realize(gtkWidget); // creates X window + + if (parent) { + Platform::internal::XSetTransientForHint(Libs::gtk_widget_get_window(gtkWidget), parent->winId()); + } + + if (modality != Qt::NonModal) { + Libs::gdk_window_set_modal_hint(Libs::gtk_widget_get_window(gtkWidget), true); + QGuiApplicationPrivate::showModalWindow(this); + } + + Libs::gtk_widget_show(gtkWidget); + Libs::gdk_window_focus(Libs::gtk_widget_get_window(gtkWidget), 0); +} + +void QGtkDialog::hide() { + QGuiApplicationPrivate::hideModalWindow(this); + Libs::gtk_widget_hide(gtkWidget); +} + +void QGtkDialog::onResponse(QGtkDialog *dialog, int response) { + if (response == GTK_RESPONSE_OK) + emit dialog->accept(); + else + emit dialog->reject(); +} + +void QGtkDialog::onParentWindowDestroyed() +{ + // The Gtk*DialogHelper classes own this object. Make sure the parent doesn't delete it. + setParent(nullptr); +} + +namespace { + +const char *filterRegExp = +"^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; + +// Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)" +QStringList cleanFilterList(const QString &filter) { + QRegExp regexp(QString::fromLatin1(filterRegExp)); + Q_ASSERT(regexp.isValid()); + QString f = filter; + int i = regexp.indexIn(f); + if (i >= 0) + f = regexp.cap(2); + return f.split(QLatin1Char(' '), QString::SkipEmptyParts); +} + +} // namespace + +GtkFileDialog::GtkFileDialog(QWidget *parent, const QString &caption, const QString &directory, const QString &filter) : QDialog(parent) +, _windowTitle(caption) +, _initialDirectory(directory) { + auto filters = qt_make_filter_list(filter); + const int numFilters = filters.count(); + _nameFilters.reserve(numFilters); + for (int i = 0; i < numFilters; ++i) { + _nameFilters << filters[i].simplified(); + } + + d.reset(new QGtkDialog(Libs::gtk_file_chooser_dialog_new("", nullptr, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OK, GTK_RESPONSE_OK, NULL))); + connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); + connect(d.data(), SIGNAL(reject()), this, SLOT(onRejected())); + + g_signal_connect(Libs::gtk_file_chooser_cast(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this); + g_signal_connect_swapped(Libs::gtk_file_chooser_cast(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this); +} + +GtkFileDialog::~GtkFileDialog() { +} + +void GtkFileDialog::showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) { + _dir.clear(); + _selection.clear(); + + applyOptions(); + return d->show(flags, modality, parent); +} + +void GtkFileDialog::setVisible(bool visible) { + if (visible) { + if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) { + return; + } + } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) { + return; + } + + if (visible) { + showHelper(windowFlags(), windowModality(), parentWidget() ? parentWidget()->windowHandle() : nullptr); + } else { + hideHelper(); + } + + // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below + // updates the state correctly, but skips showing the non-native version: + setAttribute(Qt::WA_DontShowOnScreen); + + QDialog::setVisible(visible); +} + +int GtkFileDialog::exec() { + d->setModality(windowModality()); + + bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose); + setAttribute(Qt::WA_DeleteOnClose, false); + + bool wasShowModal = testAttribute(Qt::WA_ShowModal); + setAttribute(Qt::WA_ShowModal, true); + setResult(0); + + show(); + + QPointer guard = this; + d->exec(); + if (guard.isNull()) + return QDialog::Rejected; + + setAttribute(Qt::WA_ShowModal, wasShowModal); + + return result(); +} + +void GtkFileDialog::hideHelper() { + // After GtkFileChooserDialog has been hidden, gtk_file_chooser_get_current_folder() + // & gtk_file_chooser_get_filenames() will return bogus values -> cache the actual + // values before hiding the dialog + _dir = directory().absolutePath(); + _selection = selectedFiles(); + + d->hide(); +} + +bool GtkFileDialog::defaultNameFilterDisables() const { + return false; +} + +void GtkFileDialog::setDirectory(const QString &directory) { + GtkDialog *gtkDialog = d->gtkDialog(); + Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), directory.toUtf8()); +} + +QDir GtkFileDialog::directory() const { + // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder() + // returns a bogus value -> return the cached value before hiding + if (!_dir.isEmpty()) + return _dir; + + QString ret; + GtkDialog *gtkDialog = d->gtkDialog(); + gchar *folder = Libs::gtk_file_chooser_get_current_folder(Libs::gtk_file_chooser_cast(gtkDialog)); + if (folder) { + ret = QString::fromUtf8(folder); + g_free(folder); + } + return QDir(ret); +} + +void GtkFileDialog::selectFile(const QString &filename) { + _initialFiles.clear(); + _initialFiles.append(filename); +} + +QStringList GtkFileDialog::selectedFiles() const { + // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames() + // returns a bogus value -> return the cached value before hiding + if (!_selection.isEmpty()) + return _selection; + + QStringList selection; + GtkDialog *gtkDialog = d->gtkDialog(); + GSList *filenames = Libs::gtk_file_chooser_get_filenames(Libs::gtk_file_chooser_cast(gtkDialog)); + for (GSList *it = filenames; it; it = it->next) + selection += QString::fromUtf8((const char*)it->data); + g_slist_free(filenames); + return selection; +} + +void GtkFileDialog::setFilter() { + applyOptions(); +} + +void GtkFileDialog::selectNameFilter(const QString &filter) { + GtkFileFilter *gtkFilter = _filters.value(filter); + if (gtkFilter) { + GtkDialog *gtkDialog = d->gtkDialog(); + Libs::gtk_file_chooser_set_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter); + } +} + +QString GtkFileDialog::selectedNameFilter() const { + GtkDialog *gtkDialog = d->gtkDialog(); + GtkFileFilter *gtkFilter = Libs::gtk_file_chooser_get_filter(Libs::gtk_file_chooser_cast(gtkDialog)); + return _filterNames.value(gtkFilter); +} + +void GtkFileDialog::onAccepted() { + emit accept(); + +// QString filter = selectedNameFilter(); +// if (filter.isEmpty()) +// emit filterSelected(filter); + +// QList files = selectedFiles(); +// emit filesSelected(files); +// if (files.count() == 1) +// emit fileSelected(files.first()); +} + +void GtkFileDialog::onRejected() { + emit reject(); + +// +} + +void GtkFileDialog::onSelectionChanged(GtkDialog *gtkDialog, GtkFileDialog *helper) { +// QString selection; +// gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtkDialog)); +// if (filename) { +// selection = QString::fromUtf8(filename); +// g_free(filename); +// } +// emit helper->currentChanged(QUrl::fromLocalFile(selection)); +} + +void GtkFileDialog::onCurrentFolderChanged(GtkFileDialog *dialog) { +// emit dialog->directoryEntered(dialog->directory()); +} + +GtkFileChooserAction gtkFileChooserAction(QFileDialog::FileMode fileMode, QFileDialog::AcceptMode acceptMode) { + switch (fileMode) { + case QFileDialog::AnyFile: + case QFileDialog::ExistingFile: + case QFileDialog::ExistingFiles: + if (acceptMode == QFileDialog::AcceptOpen) + return GTK_FILE_CHOOSER_ACTION_OPEN; + else + return GTK_FILE_CHOOSER_ACTION_SAVE; + case QFileDialog::Directory: + case QFileDialog::DirectoryOnly: + default: + if (acceptMode == QFileDialog::AcceptOpen) + return GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + else + return GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; + } +} + +bool CustomButtonsSupported() { + return (Libs::gtk_dialog_get_widget_for_response != nullptr) + && (Libs::gtk_button_set_label != nullptr) + && (Libs::gtk_button_get_type != nullptr); +} + +void GtkFileDialog::applyOptions() { + GtkDialog *gtkDialog = d->gtkDialog(); + + Libs::gtk_window_set_title(Libs::gtk_window_cast(gtkDialog), _windowTitle.toUtf8()); + Libs::gtk_file_chooser_set_local_only(Libs::gtk_file_chooser_cast(gtkDialog), true); + + const GtkFileChooserAction action = gtkFileChooserAction(_fileMode, _acceptMode); + Libs::gtk_file_chooser_set_action(Libs::gtk_file_chooser_cast(gtkDialog), action); + + const bool selectMultiple = (_fileMode == QFileDialog::ExistingFiles); + Libs::gtk_file_chooser_set_select_multiple(Libs::gtk_file_chooser_cast(gtkDialog), selectMultiple); + + const bool confirmOverwrite = !_options.testFlag(QFileDialog::DontConfirmOverwrite); + Libs::gtk_file_chooser_set_do_overwrite_confirmation(Libs::gtk_file_chooser_cast(gtkDialog), confirmOverwrite); + + if (!_nameFilters.isEmpty()) + setNameFilters(_nameFilters); + + if (!_initialDirectory.isEmpty()) + setDirectory(_initialDirectory); + + for_const (const auto &filename, _initialFiles) { + if (_acceptMode == QFileDialog::AcceptSave) { + QFileInfo fi(filename); + Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), fi.path().toUtf8()); + Libs::gtk_file_chooser_set_current_name(Libs::gtk_file_chooser_cast(gtkDialog), fi.fileName().toUtf8()); + } else if (filename.endsWith('/')) { + Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8()); + } else { + Libs::gtk_file_chooser_select_filename(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8()); + } + } + + const QString initialNameFilter = _nameFilters.isEmpty() ? QString() : _nameFilters.front(); + if (!initialNameFilter.isEmpty()) + selectNameFilter(initialNameFilter); + + if (CustomButtonsSupported()) { + GtkWidget *acceptButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK); + if (acceptButton) { + /*if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept)) + Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8()); + else*/ if (_acceptMode == QFileDialog::AcceptOpen) + Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_OPEN); + else + Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_SAVE); + } + + GtkWidget *rejectButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_CANCEL); + if (rejectButton) { + /*if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject)) + Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8()); + else*/ + Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), GTK_STOCK_CANCEL); + } + } +} + +void GtkFileDialog::setNameFilters(const QStringList &filters) { + GtkDialog *gtkDialog = d->gtkDialog(); + foreach (GtkFileFilter *filter, _filters) + Libs::gtk_file_chooser_remove_filter(Libs::gtk_file_chooser_cast(gtkDialog), filter); + + _filters.clear(); + _filterNames.clear(); + + foreach (const QString &filter, filters) { + GtkFileFilter *gtkFilter = Libs::gtk_file_filter_new(); + const QString name = filter.left(filter.indexOf(QLatin1Char('('))); + const QStringList extensions = cleanFilterList(filter); + + Libs::gtk_file_filter_set_name(gtkFilter, name.isEmpty() ? extensions.join(QStringLiteral(", ")).toUtf8() : name.toUtf8()); + foreach (const QString &ext, extensions) + Libs::gtk_file_filter_add_pattern(gtkFilter, ext.toUtf8()); + + Libs::gtk_file_chooser_add_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter); + + _filters.insert(filter, gtkFilter); + _filterNames.insert(gtkFilter, filter); + } +} + +} // namespace internal +} // namespace FileDialog +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/file_dialog_linux.h b/Telegram/SourceFiles/platform/linux/file_dialog_linux.h new file mode 100644 index 000000000..3cc2a935d --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/file_dialog_linux.h @@ -0,0 +1,145 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "ui/filedialog.h" + +extern "C" { +#undef signals +#include +#include +#define signals public +} // extern "C" + +namespace Platform { +namespace FileDialog { + +bool Supported(); + +bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile); + +namespace internal { + +// This is a patched copy of qgtk2 theme plugin. +// We need to use our own gtk file dialog instead of +// styling Qt file dialog, because Qt only works with gtk2. +// We need to be able to work with gtk2 and gtk3, because +// we use gtk3 to work with appindicator3. +class QGtkDialog : public QWindow { + Q_OBJECT + +public: + QGtkDialog(GtkWidget *gtkWidget); + ~QGtkDialog(); + + GtkDialog *gtkDialog() const; + + void exec(); + void show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent); + void hide(); + +signals: + void accept(); + void reject(); + +protected: + static void onResponse(QGtkDialog *dialog, int response); + +private slots: + void onParentWindowDestroyed(); + +private: + GtkWidget *gtkWidget; + +}; + +class GtkFileDialog : public QDialog { + Q_OBJECT + +public: + GtkFileDialog(QWidget *parent = Q_NULLPTR, + const QString &caption = QString(), + const QString &directory = QString(), + const QString &filter = QString()); + ~GtkFileDialog(); + + void setVisible(bool visible) override; + + void setWindowTitle(const QString &windowTitle) { + _windowTitle = windowTitle; + } + void setAcceptMode(QFileDialog::AcceptMode acceptMode) { + _acceptMode = acceptMode; + } + void setFileMode(QFileDialog::FileMode fileMode) { + _fileMode = fileMode; + } + void setOption(QFileDialog::Option option, bool on = true) { + if (on) { + _options |= option; + } else { + _options &= ~option; + } + } + + int exec() override; + + bool defaultNameFilterDisables() const; + void setDirectory(const QString &directory); + QDir directory() const; + void selectFile(const QString &filename); + QStringList selectedFiles() const; + void setFilter(); + void selectNameFilter(const QString &filter); + QString selectedNameFilter() const; + +private slots: + void onAccepted(); + void onRejected(); + +private: + static void onSelectionChanged(GtkDialog *dialog, GtkFileDialog *helper); + static void onCurrentFolderChanged(GtkFileDialog *helper); + void applyOptions(); + void setNameFilters(const QStringList &filters); + + void showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent); + void hideHelper(); + + // Options + QFileDialog::Options _options = { 0 }; + QString _windowTitle = "Choose file"; + QString _initialDirectory; + QStringList _initialFiles; + QStringList _nameFilters; + QFileDialog::AcceptMode _acceptMode = QFileDialog::AcceptOpen; + QFileDialog::FileMode _fileMode = QFileDialog::ExistingFile; + + QString _dir; + QStringList _selection; + QHash _filters; + QHash _filterNames; + QScopedPointer d; +}; + +} // namespace internal +} // namespace FileDialog +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp new file mode 100644 index 000000000..80d29af2d --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp @@ -0,0 +1,118 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#include "stdafx.h" +#include "platform/linux/linux_gdk_helper.h" + +#include "platform/linux/linux_libs.h" + +extern "C" { +#undef signals +#include +#define signals public +} // extern "C" + +namespace Platform { +namespace internal { + +enum class GtkLoaded { + GtkNone, + Gtk2, + Gtk3, +}; + +GtkLoaded gdk_helper_loaded = GtkLoaded::GtkNone; + +// To be able to compile with gtk-3.0 headers as well +#define GdkDrawable GdkWindow + +// Gtk 2 +using f_gdk_x11_drawable_get_xdisplay = Display*(*)(GdkDrawable*); +f_gdk_x11_drawable_get_xdisplay gdk_x11_drawable_get_xdisplay = nullptr; + +using f_gdk_x11_drawable_get_xid = XID(*)(GdkDrawable*); +f_gdk_x11_drawable_get_xid gdk_x11_drawable_get_xid = nullptr; + +// Gtk 3 + +// To be able to compile with gtk-2.0 headers as well +#ifndef GDK_TYPE_X11_WINDOW +#define GDK_TYPE_X11_WINDOW (gdk_x11_window_get_type()) +#endif // GDK_TYPE_X11_WINDOW + +#ifndef GDK_IS_X11_WINDOW +#define GDK_IS_X11_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), GDK_TYPE_X11_WINDOW)) +#endif // GDK_IS_X11_WINDOW + +using f_gdk_x11_window_get_type = GType (*)(void); +f_gdk_x11_window_get_type gdk_x11_window_get_type = nullptr; + +using f_gdk_window_get_display = GdkDisplay*(*)(GdkWindow *window); +f_gdk_window_get_display gdk_window_get_display = nullptr; + +using f_gdk_x11_display_get_xdisplay = Display*(*)(GdkDisplay *display); +f_gdk_x11_display_get_xdisplay gdk_x11_display_get_xdisplay = nullptr; + +using f_gdk_x11_window_get_xid = Window(*)(GdkWindow *window); +f_gdk_x11_window_get_xid gdk_x11_window_get_xid = nullptr; + +bool GdkHelperLoadGtk2(QLibrary &lib) { + if (!Libs::load(lib, "gdk_x11_drawable_get_xdisplay", gdk_x11_drawable_get_xdisplay)) return false; + if (!Libs::load(lib, "gdk_x11_drawable_get_xid", gdk_x11_drawable_get_xid)) return false; + return true; +} + +bool GdkHelperLoadGtk3(QLibrary &lib) { + if (!Libs::load(lib, "gdk_x11_window_get_type", gdk_x11_window_get_type)) return false; + if (!Libs::load(lib, "gdk_window_get_display", gdk_window_get_display)) return false; + if (!Libs::load(lib, "gdk_x11_display_get_xdisplay", gdk_x11_display_get_xdisplay)) return false; + if (!Libs::load(lib, "gdk_x11_window_get_xid", gdk_x11_window_get_xid)) return false; + return true; +} + +void GdkHelperLoad(QLibrary &lib) { + gdk_helper_loaded = GtkLoaded::GtkNone; + if (GdkHelperLoadGtk2(lib)) { + gdk_helper_loaded = GtkLoaded::Gtk2; + } else if (GdkHelperLoadGtk3(lib)) { + gdk_helper_loaded = GtkLoaded::Gtk3; + } +} + +bool GdkHelperLoaded() { + return gdk_helper_loaded != GtkLoaded::GtkNone; +} + +void XSetTransientForHint(GdkWindow *window, quintptr winId) { + if (gdk_helper_loaded == GtkLoaded::Gtk2) { + ::XSetTransientForHint(gdk_x11_drawable_get_xdisplay(window), + gdk_x11_drawable_get_xid(window), + winId); + } else if (gdk_helper_loaded == GtkLoaded::Gtk3) { + if (GDK_IS_X11_WINDOW(window)) { + ::XSetTransientForHint(gdk_x11_display_get_xdisplay(gdk_window_get_display(window)), + gdk_x11_window_get_xid(window), + winId); + } + } +} + +} // namespace internal +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h new file mode 100644 index 000000000..dd049480b --- /dev/null +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h @@ -0,0 +1,40 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include + +extern "C" { +#undef signals +#include +#include +#define signals public +} // extern "C" + +namespace Platform { +namespace internal { + +void GdkHelperLoad(QLibrary &lib); +bool GdkHelperLoaded(); +void XSetTransientForHint(GdkWindow *window, quintptr winId); + +} // namespace internal +} // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.cpp b/Telegram/SourceFiles/platform/linux/linux_libs.cpp index 4d1ba3d80..3311ddca3 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libs.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_libs.cpp @@ -21,6 +21,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "stdafx.h" #include "platform/linux/linux_libs.h" +#include "platform/linux/linux_gdk_helper.h" + namespace Platform { namespace Libs { namespace { @@ -42,27 +44,59 @@ bool loadLibrary(QLibrary &lib, const char *name, int version) { } bool setupGtkBase(QLibrary &lib_gtk) { - if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false; - if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false; - if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false; + if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false; + if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false; + if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false; - if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false; - if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false; - if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false; - if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false; - if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false; - if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false; - if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false; - if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false; + if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false; + if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false; + if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false; + if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false; + if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false; + if (!load(lib_gtk, "gtk_widget_hide", gtk_widget_hide)) return false; + if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false; + if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false; + if (!load(lib_gtk, "gtk_widget_get_window", gtk_widget_get_window)) return false; + if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false; + if (!load(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false; + if (!load(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false; + if (!load(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false; + if (!load(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false; + if (!load(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false; + if (!load(lib_gtk, "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new)) return false; + if (!load(lib_gtk, "gtk_file_chooser_get_type", gtk_file_chooser_get_type)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_current_folder", gtk_file_chooser_set_current_folder)) return false; + if (!load(lib_gtk, "gtk_file_chooser_get_current_folder", gtk_file_chooser_get_current_folder)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_current_name", gtk_file_chooser_set_current_name)) return false; + if (!load(lib_gtk, "gtk_file_chooser_select_filename", gtk_file_chooser_select_filename)) return false; + if (!load(lib_gtk, "gtk_file_chooser_get_filenames", gtk_file_chooser_get_filenames)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_filter", gtk_file_chooser_set_filter)) return false; + if (!load(lib_gtk, "gtk_file_chooser_get_filter", gtk_file_chooser_get_filter)) return false; + if (!load(lib_gtk, "gtk_window_get_type", gtk_window_get_type)) return false; + if (!load(lib_gtk, "gtk_window_set_title", gtk_window_set_title)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_local_only", gtk_file_chooser_set_local_only)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_action", gtk_file_chooser_set_action)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_select_multiple", gtk_file_chooser_set_select_multiple)) return false; + if (!load(lib_gtk, "gtk_file_chooser_set_do_overwrite_confirmation", gtk_file_chooser_set_do_overwrite_confirmation)) return false; + if (!load(lib_gtk, "gtk_file_chooser_remove_filter", gtk_file_chooser_remove_filter)) return false; + if (!load(lib_gtk, "gtk_file_filter_set_name", gtk_file_filter_set_name)) return false; + if (!load(lib_gtk, "gtk_file_filter_add_pattern", gtk_file_filter_add_pattern)) return false; + if (!load(lib_gtk, "gtk_file_chooser_add_filter", gtk_file_chooser_add_filter)) return false; + if (!load(lib_gtk, "gtk_file_filter_new", gtk_file_filter_new)) return false; - if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false; - if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false; + if (!load(lib_gtk, "gdk_window_set_modal_hint", gdk_window_set_modal_hint)) return false; + if (!load(lib_gtk, "gdk_window_focus", gdk_window_focus)) return false; + if (!load(lib_gtk, "gtk_dialog_get_type", gtk_dialog_get_type)) return false; + if (!load(lib_gtk, "gtk_dialog_run", gtk_dialog_run)) return false; - if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false; - if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false; + if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false; + if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false; - DEBUG_LOG(("Library gtk functions loaded!")); - if (!gtk_init_check(0, 0)) { + if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false; + if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false; + + DEBUG_LOG(("Library gtk functions loaded!")); + if (!gtk_init_check(0, 0)) { gtk_init_check = nullptr; DEBUG_LOG(("Failed to gtk_init_check(0, 0)!")); return false; @@ -73,12 +107,12 @@ bool setupGtkBase(QLibrary &lib_gtk) { } bool setupAppIndicator(QLibrary &lib_indicator) { - if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false; - if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false; - if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false; - if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false; + if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false; + if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false; + if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false; + if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false; - DEBUG_LOG(("Library appindicator functions loaded!")); + DEBUG_LOG(("Library appindicator functions loaded!")); return true; } @@ -92,9 +126,43 @@ f_gtk_menu_item_set_label gtk_menu_item_set_label = nullptr; f_gtk_menu_shell_append gtk_menu_shell_append = nullptr; f_gtk_menu_shell_get_type gtk_menu_shell_get_type = nullptr; f_gtk_widget_show gtk_widget_show = nullptr; +f_gtk_widget_hide gtk_widget_hide = nullptr; f_gtk_widget_get_toplevel gtk_widget_get_toplevel = nullptr; f_gtk_widget_get_visible gtk_widget_get_visible = nullptr; +f_gtk_widget_get_window gtk_widget_get_window = nullptr; f_gtk_widget_set_sensitive gtk_widget_set_sensitive = nullptr; +f_gtk_widget_realize gtk_widget_realize = nullptr; +f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete = nullptr; +f_gtk_widget_destroy gtk_widget_destroy = nullptr; +f_gtk_clipboard_get gtk_clipboard_get = nullptr; +f_gtk_clipboard_store gtk_clipboard_store = nullptr; +f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new = nullptr; +f_gtk_file_chooser_get_type gtk_file_chooser_get_type = nullptr; +f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder = nullptr; +f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder = nullptr; +f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name = nullptr; +f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename = nullptr; +f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames = nullptr; +f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter = nullptr; +f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter = nullptr; +f_gtk_window_get_type gtk_window_get_type = nullptr; +f_gtk_window_set_title gtk_window_set_title = nullptr; +f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only = nullptr; +f_gtk_file_chooser_set_action gtk_file_chooser_set_action = nullptr; +f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple = nullptr; +f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation = nullptr; +f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter = nullptr; +f_gtk_file_filter_set_name gtk_file_filter_set_name = nullptr; +f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern = nullptr; +f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter = nullptr; +f_gtk_file_filter_new gtk_file_filter_new = nullptr; +f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response = nullptr; +f_gtk_button_set_label gtk_button_set_label = nullptr; +f_gtk_button_get_type gtk_button_get_type = nullptr; +f_gdk_window_set_modal_hint gdk_window_set_modal_hint = nullptr; +f_gdk_window_focus gdk_window_focus = nullptr; +f_gtk_dialog_get_type gtk_dialog_get_type = nullptr; +f_gtk_dialog_run gtk_dialog_run = nullptr; f_g_type_check_instance_cast g_type_check_instance_cast = nullptr; f_g_signal_connect_data g_signal_connect_data = nullptr; f_app_indicator_new app_indicator_new = nullptr; @@ -172,6 +240,12 @@ void start() { load(lib_gtk, "gtk_menu_popup", gtk_menu_popup); load(lib_gtk, "gtk_get_current_event_time", gtk_get_current_event_time); load(lib_gtk, "g_idle_add", g_idle_add); + + internal::GdkHelperLoad(lib_gtk); + + load(lib_gtk, "gtk_dialog_get_widget_for_response", gtk_dialog_get_widget_for_response); + load(lib_gtk, "gtk_button_set_label", gtk_button_set_label); + load(lib_gtk, "gtk_button_get_type", gtk_button_get_type); } else { LOG(("Could not load gtk-x11-2.0!")); } diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.h b/Telegram/SourceFiles/platform/linux/linux_libs.h index 3376f6965..b83214be5 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libs.h +++ b/Telegram/SourceFiles/platform/linux/linux_libs.h @@ -24,6 +24,7 @@ extern "C" { #undef signals #include #include +#include #define signals public } // extern "C" @@ -75,15 +76,102 @@ extern f_gtk_menu_shell_get_type gtk_menu_shell_get_type; typedef void (*f_gtk_widget_show)(GtkWidget *widget); extern f_gtk_widget_show gtk_widget_show; +typedef void (*f_gtk_widget_hide)(GtkWidget *widget); +extern f_gtk_widget_hide gtk_widget_hide; + typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget); extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel; typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget); extern f_gtk_widget_get_visible gtk_widget_get_visible; +typedef GdkWindow* (*f_gtk_widget_get_window)(GtkWidget *widget); +extern f_gtk_widget_get_window gtk_widget_get_window; + typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive); extern f_gtk_widget_set_sensitive gtk_widget_set_sensitive; +typedef void (*f_gtk_widget_realize)(GtkWidget *widget); +extern f_gtk_widget_realize gtk_widget_realize; + +typedef gboolean (*f_gtk_widget_hide_on_delete)(GtkWidget *widget); +extern f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete; + +typedef void (*f_gtk_widget_destroy)(GtkWidget *widget); +extern f_gtk_widget_destroy gtk_widget_destroy; + +typedef GtkClipboard* (*f_gtk_clipboard_get)(GdkAtom selection); +extern f_gtk_clipboard_get gtk_clipboard_get; + +typedef void (*f_gtk_clipboard_store)(GtkClipboard *clipboard); +extern f_gtk_clipboard_store gtk_clipboard_store; + +typedef GtkWidget* (*f_gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...) G_GNUC_NULL_TERMINATED; +extern f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new; + +typedef gboolean (*f_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, const gchar *filename); +extern f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder; + +typedef gchar *(*f_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); +extern f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder; + +typedef void (*f_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, const gchar *name); +extern f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name; + +typedef gboolean (*f_gtk_file_chooser_select_filename)(GtkFileChooser *chooser, const char *filename); +extern f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename; + +typedef GSList* (*f_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +extern f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames; + +typedef void (*f_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); +extern f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter; + +typedef GtkFileFilter* (*f_gtk_file_chooser_get_filter)(GtkFileChooser *chooser); +extern f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter; + +typedef void (*f_gtk_window_set_title)(GtkWindow *window, const gchar *title); +extern f_gtk_window_set_title gtk_window_set_title; + +typedef void (*f_gtk_file_chooser_set_local_only)(GtkFileChooser *chooser, gboolean local_only); +extern f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only; + +typedef void (*f_gtk_file_chooser_set_action)(GtkFileChooser *chooser, GtkFileChooserAction action); +extern f_gtk_file_chooser_set_action gtk_file_chooser_set_action; + +typedef void (*f_gtk_file_chooser_set_select_multiple)(GtkFileChooser *chooser, gboolean select_multiple); +extern f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple; + +typedef void (*f_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *chooser, gboolean do_overwrite_confirmation); +extern f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation; + +typedef GtkWidget* (*f_gtk_dialog_get_widget_for_response)(GtkDialog *dialog, gint response_id); +extern f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response; + +typedef void (*f_gtk_button_set_label)(GtkButton *button, const gchar *label); +extern f_gtk_button_set_label gtk_button_set_label; + +typedef void (*f_gtk_file_chooser_remove_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); +extern f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter; + +typedef void (*f_gtk_file_filter_set_name)(GtkFileFilter *filter, const gchar *name); +extern f_gtk_file_filter_set_name gtk_file_filter_set_name; + +typedef void (*f_gtk_file_filter_add_pattern)(GtkFileFilter *filter, const gchar *pattern); +extern f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern; + +typedef void (*f_gtk_file_chooser_add_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); +extern f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter; + +typedef GtkFileFilter* (*f_gtk_file_filter_new)(void); +extern f_gtk_file_filter_new gtk_file_filter_new; + +typedef void (*f_gdk_window_set_modal_hint)(GdkWindow *window, gboolean modal); +extern f_gdk_window_set_modal_hint gdk_window_set_modal_hint; + +typedef void (*f_gdk_window_focus)(GdkWindow *window, guint32 timestamp); +extern f_gdk_window_focus gdk_window_focus; + typedef GTypeInstance* (*f_g_type_check_instance_cast)(GTypeInstance *instance, GType iface_type); extern f_g_type_check_instance_cast g_type_check_instance_cast; @@ -91,15 +179,52 @@ template inline Result *g_type_cic_helper(Object *instance, GType iface_type) { return reinterpret_cast(g_type_check_instance_cast(reinterpret_cast(instance), iface_type)); } + template inline GtkMenu *gtk_menu_cast(Object *obj) { return g_type_cic_helper(obj, gtk_menu_get_type()); } + template inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) { return g_type_cic_helper(obj, gtk_menu_get_type()); } +typedef GType (*f_gtk_dialog_get_type)(void) G_GNUC_CONST; +extern f_gtk_dialog_get_type gtk_dialog_get_type; + +template +inline GtkDialog *gtk_dialog_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_dialog_get_type()); +} + +typedef GType (*f_gtk_file_chooser_get_type)(void) G_GNUC_CONST; +extern f_gtk_file_chooser_get_type gtk_file_chooser_get_type; + +template +inline GtkFileChooser *gtk_file_chooser_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_file_chooser_get_type()); +} + +typedef GType (*f_gtk_button_get_type)(void) G_GNUC_CONST; +extern f_gtk_button_get_type gtk_button_get_type; + +template +inline GtkButton *gtk_button_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_button_get_type()); +} + +typedef GType (*f_gtk_window_get_type)(void) G_GNUC_CONST; +extern f_gtk_window_get_type gtk_window_get_type; + +template +inline GtkWindow *gtk_window_cast(Object *obj) { + return g_type_cic_helper(obj, gtk_window_get_type()); +} + +typedef gint (*f_gtk_dialog_run)(GtkDialog *dialog); +extern f_gtk_dialog_run gtk_dialog_run; + typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); extern f_g_signal_connect_data g_signal_connect_data; inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data) { diff --git a/Telegram/SourceFiles/platform/platform_file_dialog.h b/Telegram/SourceFiles/platform/platform_file_dialog.h new file mode 100644 index 000000000..c3d91d84e --- /dev/null +++ b/Telegram/SourceFiles/platform/platform_file_dialog.h @@ -0,0 +1,61 @@ +/* +This file is part of Telegram Desktop, +the official desktop version of Telegram messaging app, see https://telegram.org + +Telegram Desktop 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 3 of the License, or +(at your option) any later version. + +It 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. + +In addition, as a special exception, the copyright holders give permission +to link the code of portions of this program with the OpenSSL library. + +Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE +Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org +*/ +#pragma once + +#include "ui/filedialog.h" + +#ifdef Q_OS_MAC +namespace Platform { + +namespace FileDialog { +inline bool Supported() { + return false; +} +inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) { + return false; +} +} // namespace FileDialog +} // namespace Platform +#elif defined Q_OS_LINUX // Q_OS_MAC +#include "platform/linux/file_dialog_linux.h" +#elif defined Q_OS_WINRT // Q_OS_MAC || Q_OS_LINUX +namespace Platform { +namespace FileDialog { +inline bool Supported() { + return false; +} +inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) { + return false; +} +} // namespace FileDialog +} // namespace Platform +#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT +namespace Platform { +namespace FileDialog { +inline bool Supported() { + return false; +} +inline bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, ::FileDialog::internal::Type type, QString startFile) { + return false; +} +} // namespace FileDialog +} // namespace Platform +#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN diff --git a/Telegram/SourceFiles/ui/filedialog.cpp b/Telegram/SourceFiles/ui/filedialog.cpp index 28e065adf..f2529eb2b 100644 --- a/Telegram/SourceFiles/ui/filedialog.cpp +++ b/Telegram/SourceFiles/ui/filedialog.cpp @@ -23,6 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org #include "application.h" #include "localstorage.h" +#include "platform/platform_file_dialog.h" void filedialogInit() { if (cDialogLastPath().isEmpty()) { @@ -69,28 +70,33 @@ void filedialogInit() { } } -// multipleFiles: 1 - multi open, 0 - single open, -1 - single save, -2 - select dir -bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, int multipleFiles, QString startFile = QString()) { +namespace FileDialog { +namespace internal { +bool getFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, FileDialog::internal::Type type, QString startFile = QString()) { filedialogInit(); + if (Platform::FileDialog::Supported()) { + return Platform::FileDialog::Get(files, remoteContent, caption, filter, type, startFile); + } + #if defined Q_OS_LINUX || defined Q_OS_MAC // use native remoteContent = QByteArray(); if (startFile.isEmpty() || startFile.at(0) != '/') { startFile = cDialogLastPath() + '/' + startFile; } - QString file; - if (multipleFiles >= 0) { + QString file; + if (type == Type::ReadFiles) { files = QFileDialog::getOpenFileNames(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter); QString path = files.isEmpty() ? QString() : QFileInfo(files.back()).absoluteDir().absolutePath(); if (!path.isEmpty() && path != cDialogLastPath()) { cSetDialogLastPath(path); Local::writeUserSettings(); } - return !files.isEmpty(); - } else if (multipleFiles < -1) { + return !files.isEmpty(); + } else if (type == Type::ReadFolder) { file = QFileDialog::getExistingDirectory(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile); - } else if (multipleFiles < 0) { + } else if (type == Type::WriteFile) { file = QFileDialog::getSaveFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter); } else { file = QFileDialog::getOpenFileName(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, startFile, filter); @@ -112,11 +118,11 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS // hack for fast non-native dialog create QFileDialog dialog(App::wnd() ? App::wnd()->filedialogParent() : 0, caption, cDialogHelperPathFinal(), filter); - dialog.setModal(true); - if (multipleFiles >= 0) { // open file or files - dialog.setFileMode(multipleFiles ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile); + dialog.setModal(true); + if (type == Type::ReadFile || type == Type::ReadFiles) { + dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile); dialog.setAcceptMode(QFileDialog::AcceptOpen); - } else if (multipleFiles < -1) { // save dir + } else if (type == Type::ReadFolder) { // save dir dialog.setAcceptMode(QFileDialog::AcceptOpen); dialog.setFileMode(QFileDialog::Directory); dialog.setOption(QFileDialog::ShowDirsOnly); @@ -127,7 +133,7 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS dialog.show(); if (!cDialogLastPath().isEmpty()) dialog.setDirectory(cDialogLastPath()); - if (multipleFiles == -1) { + if (type == Type::WriteFile) { QString toSelect(startFile); #ifdef Q_OS_WIN int32 lastSlash = toSelect.lastIndexOf('/'); @@ -151,12 +157,12 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS } if (res == QDialog::Accepted) { - if (multipleFiles > 0) { + if (type == Type::ReadFiles) { files = dialog.selectedFiles(); } else { files = dialog.selectedFiles().mid(0, 1); } - if (multipleFiles >= 0) { + if (type == Type::ReadFile || type == Type::ReadFiles) { #if defined Q_OS_WIN && !defined Q_OS_WINRT remoteContent = dialog.selectedRemoteContent(); #endif // Q_OS_WIN && !Q_OS_WINRT @@ -169,13 +175,16 @@ bool _filedialogGetFiles(QStringList &files, QByteArray &remoteContent, const QS return false; } +} // namespace internal +} // namespace FileDialog + bool filedialogGetOpenFiles(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter) { - return _filedialogGetFiles(files, remoteContent, caption, filter, 1); + return FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFiles); } bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QString &caption, const QString &filter) { QStringList files; - bool result = _filedialogGetFiles(files, remoteContent, caption, filter, 0); + bool result = FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::ReadFile); file = files.isEmpty() ? QString() : files.at(0); return result; } @@ -183,7 +192,7 @@ bool filedialogGetOpenFile(QString &file, QByteArray &remoteContent, const QStri bool filedialogGetSaveFile(QString &file, const QString &caption, const QString &filter, const QString &startName) { QStringList files; QByteArray remoteContent; - bool result = _filedialogGetFiles(files, remoteContent, caption, filter, -1, startName); + bool result = FileDialog::internal::getFiles(files, remoteContent, caption, filter, FileDialog::internal::Type::WriteFile, startName); file = files.isEmpty() ? QString() : files.at(0); return result; } @@ -191,7 +200,7 @@ bool filedialogGetSaveFile(QString &file, const QString &caption, const QString bool filedialogGetDir(QString &dir, const QString &caption) { QStringList files; QByteArray remoteContent; - bool result = _filedialogGetFiles(files, remoteContent, caption, QString(), -2); + bool result = FileDialog::internal::getFiles(files, remoteContent, caption, QString(), FileDialog::internal::Type::ReadFolder); dir = files.isEmpty() ? QString() : files.at(0); return result; } diff --git a/Telegram/SourceFiles/ui/filedialog.h b/Telegram/SourceFiles/ui/filedialog.h index 9a8317e37..6ca2bf693 100644 --- a/Telegram/SourceFiles/ui/filedialog.h +++ b/Telegram/SourceFiles/ui/filedialog.h @@ -32,6 +32,16 @@ QString filedialogDefaultName(const QString &prefix, const QString &extension, c QString filedialogNextFilename(const QString &name, const QString &cur, const QString &path = QString()); namespace FileDialog { +namespace internal { + +enum class Type { + ReadFile, + ReadFiles, + ReadFolder, + WriteFile, +}; + +} // namespace internal using QueryId = uint64; struct QueryUpdate { diff --git a/Telegram/Telegram.pro b/Telegram/Telegram.pro index 8651364b3..cebef44b7 100644 --- a/Telegram/Telegram.pro +++ b/Telegram/Telegram.pro @@ -3,60 +3,60 @@ QT += core gui network widgets CONFIG += plugin static c++14 CONFIG(debug, debug|release) { - DEFINES += _DEBUG - OBJECTS_DIR = ./../DebugIntermediate - MOC_DIR = ./GeneratedFiles/Debug - RCC_DIR = ./GeneratedFiles - DESTDIR = ./../Debug + DEFINES += _DEBUG + OBJECTS_DIR = ./../DebugIntermediate + MOC_DIR = ./GeneratedFiles/Debug + RCC_DIR = ./GeneratedFiles + DESTDIR = ./../Debug } CONFIG(release, debug|release) { - DEFINES += CUSTOM_API_ID - OBJECTS_DIR = ./../ReleaseIntermediate - MOC_DIR = ./GeneratedFiles/Release - RCC_DIR = ./GeneratedFiles - DESTDIR = ./../Release + DEFINES += CUSTOM_API_ID + OBJECTS_DIR = ./../ReleaseIntermediate + MOC_DIR = ./GeneratedFiles/Release + RCC_DIR = ./GeneratedFiles + DESTDIR = ./../Release } macx { - QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist - QMAKE_LFLAGS += -framework Cocoa + QMAKE_INFO_PLIST = ./SourceFiles/Telegram.plist + QMAKE_LFLAGS += -framework Cocoa } linux { - SOURCES += ./SourceFiles/pspecific_linux.cpp - HEADERS += ./SourceFiles/pspecific_linux.h + SOURCES += ./SourceFiles/pspecific_linux.cpp + HEADERS += ./SourceFiles/pspecific_linux.h } CONFIG(debug, debug|release) { - codegen_style.target = style_target - codegen_style.depends = FORCE - codegen_style.commands = ./../codegen/Debug/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild + codegen_style.target = style_target + codegen_style.depends = FORCE + codegen_style.commands = ./../codegen/Debug/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild - codegen_numbers.target = numbers_target - codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt - codegen_numbers.commands = ./../codegen/Debug/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt" + codegen_numbers.target = numbers_target + codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt + codegen_numbers.commands = ./../codegen/Debug/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt" - codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Debug/codegen_numbers "-o./../Linux/DebugIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/DebugIntermediate + codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Debug/codegen_numbers "-o./../Linux/DebugIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/DebugIntermediate - codegen_lang.target = lang_target - codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings - codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../DebugLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto + codegen_lang.target = lang_target + codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings + codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../DebugLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto } CONFIG(release, debug|release) { - codegen_style.target = style_target - codegen_style.depends = FORCE - codegen_style.commands = ./../codegen/Release/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild + codegen_style.target = style_target + codegen_style.depends = FORCE + codegen_style.commands = ./../codegen/Release/codegen_style "-I./../../Telegram/Resources" "-I./../../Telegram/SourceFiles" "-o./GeneratedFiles/styles" all_files.style --rebuild - codegen_numbers.target = numbers_target - codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt - codegen_numbers.commands = ./../codegen/Release/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt" + codegen_numbers.target = numbers_target + codegen_numbers.depends = ./../../Telegram/Resources/numbers.txt + codegen_numbers.commands = ./../codegen/Release/codegen_numbers "-o./GeneratedFiles" "./../../Telegram/Resources/numbers.txt" - codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Release/codegen_numbers "-o./../Linux/ReleaseIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/ReleaseIntermediate + codegen_numbers.commands = cd ../../Telegram && ./../Linux/codegen/Release/codegen_numbers "-o./../Linux/ReleaseIntermediate/GeneratedFiles" "./Resources/numbers.txt" && cd ../Linux/ReleaseIntermediate - codegen_lang.target = lang_target - codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings - codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../ReleaseLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto + codegen_lang.target = lang_target + codegen_lang.depends = ./../../Telegram/Resources/langs/lang.strings + codegen_lang.commands = mkdir -p ./GeneratedFiles && ./../ReleaseLang/MetaLang -lang_in ./../../Telegram/Resources/langs/lang.strings -lang_out ./GeneratedFiles/lang_auto } file_style_basic.target = GeneratedFiles/styles/style_basic.cpp @@ -73,374 +73,379 @@ file_style_profile.target = GeneratedFiles/styles/style_profile.cpp file_style_profile.depends = style_target QMAKE_EXTRA_TARGETS += codegen_style codegen_numbers codegen_lang \ - file_style_basic file_style_basic_types file_style_overview \ - file_style_dialogs file_style_history file_style_profile + file_style_basic file_style_basic_types file_style_overview \ + file_style_dialogs file_style_history file_style_profile PRE_TARGETDEPS += style_target numbers_target lang_target unix { - linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch - linux-g++-32:QMAKE_TARGET.arch = x86 - linux-g++-64:QMAKE_TARGET.arch = x86_64 + linux-g++:QMAKE_TARGET.arch = $$QMAKE_HOST.arch + linux-g++-32:QMAKE_TARGET.arch = x86 + linux-g++-64:QMAKE_TARGET.arch = x86_64 - contains(QMAKE_TARGET.arch, x86_64) { - DEFINES += Q_OS_LINUX64 - } else { - DEFINES += Q_OS_LINUX32 - } + contains(QMAKE_TARGET.arch, x86_64) { + DEFINES += Q_OS_LINUX64 + } else { + DEFINES += Q_OS_LINUX32 + } } SOURCES += \ - ./GeneratedFiles/lang_auto.cpp \ - ./GeneratedFiles/numbers.cpp \ - ./GeneratedFiles/styles/style_basic.cpp \ - ./GeneratedFiles/styles/style_basic_types.cpp \ - ./GeneratedFiles/styles/style_dialogs.cpp \ - ./GeneratedFiles/styles/style_history.cpp \ - ./GeneratedFiles/styles/style_overview.cpp \ - ./GeneratedFiles/styles/style_profile.cpp \ - ./SourceFiles/main.cpp \ - ./SourceFiles/stdafx.cpp \ - ./SourceFiles/apiwrap.cpp \ - ./SourceFiles/app.cpp \ - ./SourceFiles/application.cpp \ - ./SourceFiles/audio.cpp \ - ./SourceFiles/autoupdater.cpp \ - ./SourceFiles/dialogswidget.cpp \ - ./SourceFiles/dropdown.cpp \ - ./SourceFiles/facades.cpp \ - ./SourceFiles/fileuploader.cpp \ - ./SourceFiles/history.cpp \ - ./SourceFiles/historywidget.cpp \ - ./SourceFiles/lang.cpp \ - ./SourceFiles/langloaderplain.cpp \ - ./SourceFiles/layerwidget.cpp \ - ./SourceFiles/layout.cpp \ - ./SourceFiles/mediaview.cpp \ - ./SourceFiles/observer_peer.cpp \ - ./SourceFiles/overviewwidget.cpp \ - ./SourceFiles/passcodewidget.cpp \ - ./SourceFiles/playerwidget.cpp \ - ./SourceFiles/localimageloader.cpp \ - ./SourceFiles/localstorage.cpp \ - ./SourceFiles/logs.cpp \ - ./SourceFiles/mainwidget.cpp \ - ./SourceFiles/settings.cpp \ - ./SourceFiles/settingswidget.cpp \ - ./SourceFiles/shortcuts.cpp \ - ./SourceFiles/structs.cpp \ - ./SourceFiles/sysbuttons.cpp \ - ./SourceFiles/title.cpp \ - ./SourceFiles/mainwindow.cpp \ - ./SourceFiles/boxes/aboutbox.cpp \ - ./SourceFiles/boxes/abstractbox.cpp \ - ./SourceFiles/boxes/addcontactbox.cpp \ - ./SourceFiles/boxes/autolockbox.cpp \ - ./SourceFiles/boxes/backgroundbox.cpp \ - ./SourceFiles/boxes/confirmbox.cpp \ - ./SourceFiles/boxes/connectionbox.cpp \ - ./SourceFiles/boxes/contactsbox.cpp \ - ./SourceFiles/boxes/downloadpathbox.cpp \ - ./SourceFiles/boxes/emojibox.cpp \ - ./SourceFiles/boxes/languagebox.cpp \ - ./SourceFiles/boxes/passcodebox.cpp \ - ./SourceFiles/boxes/photocropbox.cpp \ - ./SourceFiles/boxes/photosendbox.cpp \ - ./SourceFiles/boxes/report_box.cpp \ - ./SourceFiles/boxes/sessionsbox.cpp \ - ./SourceFiles/boxes/stickersetbox.cpp \ - ./SourceFiles/boxes/usernamebox.cpp \ - ./SourceFiles/core/basic_types.cpp \ - ./SourceFiles/core/click_handler.cpp \ - ./SourceFiles/core/click_handler_types.cpp \ - ./SourceFiles/core/observer.cpp \ - ./SourceFiles/data/data_abstract_structure.cpp \ - ./SourceFiles/data/data_drafts.cpp \ - ./SourceFiles/dialogs/dialogs_indexed_list.cpp \ - ./SourceFiles/dialogs/dialogs_layout.cpp \ - ./SourceFiles/dialogs/dialogs_list.cpp \ - ./SourceFiles/dialogs/dialogs_row.cpp \ - ./SourceFiles/history/field_autocomplete.cpp \ - ./SourceFiles/history/history_service_layout.cpp \ - ./SourceFiles/inline_bots/inline_bot_layout_internal.cpp \ - ./SourceFiles/inline_bots/inline_bot_layout_item.cpp \ - ./SourceFiles/inline_bots/inline_bot_result.cpp \ - ./SourceFiles/inline_bots/inline_bot_send_data.cpp \ - ./SourceFiles/intro/introwidget.cpp \ - ./SourceFiles/intro/introcode.cpp \ - ./SourceFiles/intro/introphone.cpp \ - ./SourceFiles/intro/intropwdcheck.cpp \ - ./SourceFiles/intro/introsignup.cpp \ - ./SourceFiles/intro/introstart.cpp \ - ./SourceFiles/mtproto/facade.cpp \ - ./SourceFiles/mtproto/auth_key.cpp \ - ./SourceFiles/mtproto/connection.cpp \ - ./SourceFiles/mtproto/connection_abstract.cpp \ - ./SourceFiles/mtproto/connection_auto.cpp \ - ./SourceFiles/mtproto/connection_http.cpp \ - ./SourceFiles/mtproto/connection_tcp.cpp \ - ./SourceFiles/mtproto/core_types.cpp \ - ./SourceFiles/mtproto/dcenter.cpp \ - ./SourceFiles/mtproto/file_download.cpp \ - ./SourceFiles/mtproto/rsa_public_key.cpp \ - ./SourceFiles/mtproto/rpc_sender.cpp \ - ./SourceFiles/mtproto/scheme_auto.cpp \ - ./SourceFiles/mtproto/session.cpp \ - ./SourceFiles/overview/overview_layout.cpp \ + ./GeneratedFiles/lang_auto.cpp \ + ./GeneratedFiles/numbers.cpp \ + ./GeneratedFiles/styles/style_basic.cpp \ + ./GeneratedFiles/styles/style_basic_types.cpp \ + ./GeneratedFiles/styles/style_dialogs.cpp \ + ./GeneratedFiles/styles/style_history.cpp \ + ./GeneratedFiles/styles/style_overview.cpp \ + ./GeneratedFiles/styles/style_profile.cpp \ + ./SourceFiles/main.cpp \ + ./SourceFiles/stdafx.cpp \ + ./SourceFiles/apiwrap.cpp \ + ./SourceFiles/app.cpp \ + ./SourceFiles/application.cpp \ + ./SourceFiles/audio.cpp \ + ./SourceFiles/autoupdater.cpp \ + ./SourceFiles/dialogswidget.cpp \ + ./SourceFiles/dropdown.cpp \ + ./SourceFiles/facades.cpp \ + ./SourceFiles/fileuploader.cpp \ + ./SourceFiles/history.cpp \ + ./SourceFiles/historywidget.cpp \ + ./SourceFiles/lang.cpp \ + ./SourceFiles/langloaderplain.cpp \ + ./SourceFiles/layerwidget.cpp \ + ./SourceFiles/layout.cpp \ + ./SourceFiles/mediaview.cpp \ + ./SourceFiles/observer_peer.cpp \ + ./SourceFiles/overviewwidget.cpp \ + ./SourceFiles/passcodewidget.cpp \ + ./SourceFiles/playerwidget.cpp \ + ./SourceFiles/localimageloader.cpp \ + ./SourceFiles/localstorage.cpp \ + ./SourceFiles/logs.cpp \ + ./SourceFiles/mainwidget.cpp \ + ./SourceFiles/settings.cpp \ + ./SourceFiles/settingswidget.cpp \ + ./SourceFiles/shortcuts.cpp \ + ./SourceFiles/structs.cpp \ + ./SourceFiles/sysbuttons.cpp \ + ./SourceFiles/title.cpp \ + ./SourceFiles/mainwindow.cpp \ + ./SourceFiles/boxes/aboutbox.cpp \ + ./SourceFiles/boxes/abstractbox.cpp \ + ./SourceFiles/boxes/addcontactbox.cpp \ + ./SourceFiles/boxes/autolockbox.cpp \ + ./SourceFiles/boxes/backgroundbox.cpp \ + ./SourceFiles/boxes/confirmbox.cpp \ + ./SourceFiles/boxes/connectionbox.cpp \ + ./SourceFiles/boxes/contactsbox.cpp \ + ./SourceFiles/boxes/downloadpathbox.cpp \ + ./SourceFiles/boxes/emojibox.cpp \ + ./SourceFiles/boxes/languagebox.cpp \ + ./SourceFiles/boxes/passcodebox.cpp \ + ./SourceFiles/boxes/photocropbox.cpp \ + ./SourceFiles/boxes/photosendbox.cpp \ + ./SourceFiles/boxes/report_box.cpp \ + ./SourceFiles/boxes/sessionsbox.cpp \ + ./SourceFiles/boxes/stickersetbox.cpp \ + ./SourceFiles/boxes/usernamebox.cpp \ + ./SourceFiles/core/basic_types.cpp \ + ./SourceFiles/core/click_handler.cpp \ + ./SourceFiles/core/click_handler_types.cpp \ + ./SourceFiles/core/observer.cpp \ + ./SourceFiles/data/data_abstract_structure.cpp \ + ./SourceFiles/data/data_drafts.cpp \ + ./SourceFiles/dialogs/dialogs_indexed_list.cpp \ + ./SourceFiles/dialogs/dialogs_layout.cpp \ + ./SourceFiles/dialogs/dialogs_list.cpp \ + ./SourceFiles/dialogs/dialogs_row.cpp \ + ./SourceFiles/history/field_autocomplete.cpp \ + ./SourceFiles/history/history_service_layout.cpp \ + ./SourceFiles/inline_bots/inline_bot_layout_internal.cpp \ + ./SourceFiles/inline_bots/inline_bot_layout_item.cpp \ + ./SourceFiles/inline_bots/inline_bot_result.cpp \ + ./SourceFiles/inline_bots/inline_bot_send_data.cpp \ + ./SourceFiles/intro/introwidget.cpp \ + ./SourceFiles/intro/introcode.cpp \ + ./SourceFiles/intro/introphone.cpp \ + ./SourceFiles/intro/intropwdcheck.cpp \ + ./SourceFiles/intro/introsignup.cpp \ + ./SourceFiles/intro/introstart.cpp \ + ./SourceFiles/mtproto/facade.cpp \ + ./SourceFiles/mtproto/auth_key.cpp \ + ./SourceFiles/mtproto/connection.cpp \ + ./SourceFiles/mtproto/connection_abstract.cpp \ + ./SourceFiles/mtproto/connection_auto.cpp \ + ./SourceFiles/mtproto/connection_http.cpp \ + ./SourceFiles/mtproto/connection_tcp.cpp \ + ./SourceFiles/mtproto/core_types.cpp \ + ./SourceFiles/mtproto/dcenter.cpp \ + ./SourceFiles/mtproto/file_download.cpp \ + ./SourceFiles/mtproto/rsa_public_key.cpp \ + ./SourceFiles/mtproto/rpc_sender.cpp \ + ./SourceFiles/mtproto/scheme_auto.cpp \ + ./SourceFiles/mtproto/session.cpp \ + ./SourceFiles/overview/overview_layout.cpp \ + ./SourceFiles/platform/linux/linux_gdk_helper.cpp \ ./SourceFiles/platform/linux/linux_libs.cpp \ - ./SourceFiles/platform/linux/main_window_linux.cpp \ - ./SourceFiles/profile/profile_actions_widget.cpp \ - ./SourceFiles/profile/profile_block_widget.cpp \ - ./SourceFiles/profile/profile_cover_drop_area.cpp \ - ./SourceFiles/profile/profile_cover.cpp \ - ./SourceFiles/profile/profile_fixed_bar.cpp \ - ./SourceFiles/profile/profile_info_widget.cpp \ - ./SourceFiles/profile/profile_inner_widget.cpp \ - ./SourceFiles/profile/profile_invite_link_widget.cpp \ - ./SourceFiles/profile/profile_members_widget.cpp \ - ./SourceFiles/profile/profile_section_memento.cpp \ - ./SourceFiles/profile/profile_settings_widget.cpp \ - ./SourceFiles/profile/profile_shared_media_widget.cpp \ - ./SourceFiles/profile/profile_userpic_button.cpp \ - ./SourceFiles/profile/profile_widget.cpp \ - ./SourceFiles/serialize/serialize_common.cpp \ - ./SourceFiles/serialize/serialize_document.cpp \ - ./SourceFiles/ui/buttons/history_down_button.cpp \ - ./SourceFiles/ui/buttons/left_outline_button.cpp \ - ./SourceFiles/ui/buttons/peer_avatar_button.cpp \ - ./SourceFiles/ui/buttons/round_button.cpp \ - ./SourceFiles/ui/style/style_core.cpp \ - ./SourceFiles/ui/style/style_core_color.cpp \ - ./SourceFiles/ui/style/style_core_font.cpp \ - ./SourceFiles/ui/style/style_core_icon.cpp \ - ./SourceFiles/ui/style/style_core_types.cpp \ - ./SourceFiles/ui/text/text.cpp \ - ./SourceFiles/ui/text/text_block.cpp \ - ./SourceFiles/ui/text/text_entity.cpp \ - ./SourceFiles/ui/toast/toast.cpp \ - ./SourceFiles/ui/toast/toast_manager.cpp \ - ./SourceFiles/ui/toast/toast_widget.cpp \ - ./SourceFiles/ui/animation.cpp \ - ./SourceFiles/ui/boxshadow.cpp \ - ./SourceFiles/ui/button.cpp \ - ./SourceFiles/ui/popupmenu.cpp \ - ./SourceFiles/ui/countryinput.cpp \ - ./SourceFiles/ui/emoji_config.cpp \ - ./SourceFiles/ui/filedialog.cpp \ - ./SourceFiles/ui/flatbutton.cpp \ - ./SourceFiles/ui/flatcheckbox.cpp \ - ./SourceFiles/ui/flatinput.cpp \ - ./SourceFiles/ui/flatlabel.cpp \ - ./SourceFiles/ui/flattextarea.cpp \ - ./SourceFiles/ui/images.cpp \ - ./SourceFiles/ui/inner_dropdown.cpp \ - ./SourceFiles/ui/scrollarea.cpp \ - ./SourceFiles/ui/twidget.cpp \ - ./SourceFiles/window/main_window.cpp \ - ./SourceFiles/window/section_widget.cpp \ - ./SourceFiles/window/slide_animation.cpp \ - ./SourceFiles/window/top_bar_widget.cpp + ./SourceFiles/platform/linux/file_dialog_linux.cpp \ + ./SourceFiles/platform/linux/main_window_linux.cpp \ + ./SourceFiles/profile/profile_actions_widget.cpp \ + ./SourceFiles/profile/profile_block_widget.cpp \ + ./SourceFiles/profile/profile_cover_drop_area.cpp \ + ./SourceFiles/profile/profile_cover.cpp \ + ./SourceFiles/profile/profile_fixed_bar.cpp \ + ./SourceFiles/profile/profile_info_widget.cpp \ + ./SourceFiles/profile/profile_inner_widget.cpp \ + ./SourceFiles/profile/profile_invite_link_widget.cpp \ + ./SourceFiles/profile/profile_members_widget.cpp \ + ./SourceFiles/profile/profile_section_memento.cpp \ + ./SourceFiles/profile/profile_settings_widget.cpp \ + ./SourceFiles/profile/profile_shared_media_widget.cpp \ + ./SourceFiles/profile/profile_userpic_button.cpp \ + ./SourceFiles/profile/profile_widget.cpp \ + ./SourceFiles/serialize/serialize_common.cpp \ + ./SourceFiles/serialize/serialize_document.cpp \ + ./SourceFiles/ui/buttons/history_down_button.cpp \ + ./SourceFiles/ui/buttons/left_outline_button.cpp \ + ./SourceFiles/ui/buttons/peer_avatar_button.cpp \ + ./SourceFiles/ui/buttons/round_button.cpp \ + ./SourceFiles/ui/style/style_core.cpp \ + ./SourceFiles/ui/style/style_core_color.cpp \ + ./SourceFiles/ui/style/style_core_font.cpp \ + ./SourceFiles/ui/style/style_core_icon.cpp \ + ./SourceFiles/ui/style/style_core_types.cpp \ + ./SourceFiles/ui/text/text.cpp \ + ./SourceFiles/ui/text/text_block.cpp \ + ./SourceFiles/ui/text/text_entity.cpp \ + ./SourceFiles/ui/toast/toast.cpp \ + ./SourceFiles/ui/toast/toast_manager.cpp \ + ./SourceFiles/ui/toast/toast_widget.cpp \ + ./SourceFiles/ui/animation.cpp \ + ./SourceFiles/ui/boxshadow.cpp \ + ./SourceFiles/ui/button.cpp \ + ./SourceFiles/ui/popupmenu.cpp \ + ./SourceFiles/ui/countryinput.cpp \ + ./SourceFiles/ui/emoji_config.cpp \ + ./SourceFiles/ui/filedialog.cpp \ + ./SourceFiles/ui/flatbutton.cpp \ + ./SourceFiles/ui/flatcheckbox.cpp \ + ./SourceFiles/ui/flatinput.cpp \ + ./SourceFiles/ui/flatlabel.cpp \ + ./SourceFiles/ui/flattextarea.cpp \ + ./SourceFiles/ui/images.cpp \ + ./SourceFiles/ui/inner_dropdown.cpp \ + ./SourceFiles/ui/scrollarea.cpp \ + ./SourceFiles/ui/twidget.cpp \ + ./SourceFiles/window/main_window.cpp \ + ./SourceFiles/window/section_widget.cpp \ + ./SourceFiles/window/slide_animation.cpp \ + ./SourceFiles/window/top_bar_widget.cpp HEADERS += \ - ./GeneratedFiles/lang_auto.h \ - ./GeneratedFiles/numbers.h \ - ./GeneratedFiles/styles/style_basic.h \ - ./GeneratedFiles/styles/style_basic_types.h \ - ./GeneratedFiles/styles/style_dialogs.h \ - ./GeneratedFiles/styles/style_history.h \ - ./GeneratedFiles/styles/style_overview.h \ - ./GeneratedFiles/styles/style_profile.h \ - ./SourceFiles/stdafx.h \ - ./SourceFiles/apiwrap.h \ - ./SourceFiles/app.h \ - ./SourceFiles/application.h \ - ./SourceFiles/audio.h \ - ./SourceFiles/autoupdater.h \ - ./SourceFiles/config.h \ - ./SourceFiles/countries.h \ - ./SourceFiles/dialogswidget.h \ - ./SourceFiles/dropdown.h \ - ./SourceFiles/facades.h \ - ./SourceFiles/fileuploader.h \ - ./SourceFiles/history.h \ - ./SourceFiles/historywidget.h \ - ./SourceFiles/lang.h \ - ./SourceFiles/langloaderplain.h \ - ./SourceFiles/layerwidget.h \ - ./SourceFiles/layout.h \ - ./SourceFiles/mediaview.h \ - ./SourceFiles/observer_peer.h \ - ./SourceFiles/overviewwidget.h \ - ./SourceFiles/passcodewidget.h \ - ./SourceFiles/playerwidget.h \ - ./SourceFiles/localimageloader.h \ - ./SourceFiles/localstorage.h \ - ./SourceFiles/logs.h \ - ./SourceFiles/mainwidget.h \ - ./SourceFiles/settings.h \ - ./SourceFiles/settingswidget.h \ - ./SourceFiles/shortcuts.h \ - ./SourceFiles/structs.h \ - ./SourceFiles/sysbuttons.h \ - ./SourceFiles/title.h \ - ./SourceFiles/mainwindow.h \ - ./SourceFiles/boxes/aboutbox.h \ - ./SourceFiles/boxes/abstractbox.h \ - ./SourceFiles/boxes/addcontactbox.h \ - ./SourceFiles/boxes/autolockbox.h \ - ./SourceFiles/boxes/backgroundbox.h \ - ./SourceFiles/boxes/confirmbox.h \ - ./SourceFiles/boxes/connectionbox.h \ - ./SourceFiles/boxes/contactsbox.h \ - ./SourceFiles/boxes/downloadpathbox.h \ - ./SourceFiles/boxes/emojibox.h \ - ./SourceFiles/boxes/languagebox.h \ - ./SourceFiles/boxes/passcodebox.h \ - ./SourceFiles/boxes/photocropbox.h \ - ./SourceFiles/boxes/photosendbox.h \ - ./SourceFiles/boxes/report_box.h \ - ./SourceFiles/boxes/sessionsbox.h \ - ./SourceFiles/boxes/stickersetbox.h \ - ./SourceFiles/boxes/usernamebox.h \ - ./SourceFiles/core/basic_types.h \ - ./SourceFiles/core/click_handler.h \ - ./SourceFiles/core/click_handler_types.h \ - ./SourceFiles/core/observer.h \ - ./SourceFiles/core/vector_of_moveable.h \ + ./GeneratedFiles/lang_auto.h \ + ./GeneratedFiles/numbers.h \ + ./GeneratedFiles/styles/style_basic.h \ + ./GeneratedFiles/styles/style_basic_types.h \ + ./GeneratedFiles/styles/style_dialogs.h \ + ./GeneratedFiles/styles/style_history.h \ + ./GeneratedFiles/styles/style_overview.h \ + ./GeneratedFiles/styles/style_profile.h \ + ./SourceFiles/stdafx.h \ + ./SourceFiles/apiwrap.h \ + ./SourceFiles/app.h \ + ./SourceFiles/application.h \ + ./SourceFiles/audio.h \ + ./SourceFiles/autoupdater.h \ + ./SourceFiles/config.h \ + ./SourceFiles/countries.h \ + ./SourceFiles/dialogswidget.h \ + ./SourceFiles/dropdown.h \ + ./SourceFiles/facades.h \ + ./SourceFiles/fileuploader.h \ + ./SourceFiles/history.h \ + ./SourceFiles/historywidget.h \ + ./SourceFiles/lang.h \ + ./SourceFiles/langloaderplain.h \ + ./SourceFiles/layerwidget.h \ + ./SourceFiles/layout.h \ + ./SourceFiles/mediaview.h \ + ./SourceFiles/observer_peer.h \ + ./SourceFiles/overviewwidget.h \ + ./SourceFiles/passcodewidget.h \ + ./SourceFiles/playerwidget.h \ + ./SourceFiles/localimageloader.h \ + ./SourceFiles/localstorage.h \ + ./SourceFiles/logs.h \ + ./SourceFiles/mainwidget.h \ + ./SourceFiles/settings.h \ + ./SourceFiles/settingswidget.h \ + ./SourceFiles/shortcuts.h \ + ./SourceFiles/structs.h \ + ./SourceFiles/sysbuttons.h \ + ./SourceFiles/title.h \ + ./SourceFiles/mainwindow.h \ + ./SourceFiles/boxes/aboutbox.h \ + ./SourceFiles/boxes/abstractbox.h \ + ./SourceFiles/boxes/addcontactbox.h \ + ./SourceFiles/boxes/autolockbox.h \ + ./SourceFiles/boxes/backgroundbox.h \ + ./SourceFiles/boxes/confirmbox.h \ + ./SourceFiles/boxes/connectionbox.h \ + ./SourceFiles/boxes/contactsbox.h \ + ./SourceFiles/boxes/downloadpathbox.h \ + ./SourceFiles/boxes/emojibox.h \ + ./SourceFiles/boxes/languagebox.h \ + ./SourceFiles/boxes/passcodebox.h \ + ./SourceFiles/boxes/photocropbox.h \ + ./SourceFiles/boxes/photosendbox.h \ + ./SourceFiles/boxes/report_box.h \ + ./SourceFiles/boxes/sessionsbox.h \ + ./SourceFiles/boxes/stickersetbox.h \ + ./SourceFiles/boxes/usernamebox.h \ + ./SourceFiles/core/basic_types.h \ + ./SourceFiles/core/click_handler.h \ + ./SourceFiles/core/click_handler_types.h \ + ./SourceFiles/core/observer.h \ + ./SourceFiles/core/vector_of_moveable.h \ ./SourceFiles/core/version.h \ - ./SourceFiles/data/data_abstract_structure.h \ - ./SourceFiles/data/data_drafts.h \ - ./SourceFiles/dialogs/dialogs_common.h \ - ./SourceFiles/dialogs/dialogs_indexed_list.h \ - ./SourceFiles/dialogs/dialogs_layout.h \ - ./SourceFiles/dialogs/dialogs_list.h \ - ./SourceFiles/dialogs/dialogs_row.h \ - ./SourceFiles/history/field_autocomplete.h \ - ./SourceFiles/history/history_common.h \ - ./SourceFiles/history/history_service_layout.h \ - ./SourceFiles/inline_bots/inline_bot_layout_internal.h \ - ./SourceFiles/inline_bots/inline_bot_layout_item.h \ - ./SourceFiles/inline_bots/inline_bot_result.h \ - ./SourceFiles/inline_bots/inline_bot_send_data.h \ - ./SourceFiles/intro/introwidget.h \ - ./SourceFiles/intro/introcode.h \ - ./SourceFiles/intro/introphone.h \ - ./SourceFiles/intro/intropwdcheck.h \ - ./SourceFiles/intro/introsignup.h \ - ./SourceFiles/intro/introstart.h \ - ./SourceFiles/mtproto/facade.h \ - ./SourceFiles/mtproto/auth_key.h \ - ./SourceFiles/mtproto/connection.h \ - ./SourceFiles/mtproto/connection_abstract.h \ - ./SourceFiles/mtproto/connection_auto.h \ - ./SourceFiles/mtproto/connection_http.h \ - ./SourceFiles/mtproto/connection_tcp.h \ - ./SourceFiles/mtproto/core_types.h \ - ./SourceFiles/mtproto/dcenter.h \ - ./SourceFiles/mtproto/file_download.h \ - ./SourceFiles/mtproto/rsa_public_key.h \ - ./SourceFiles/mtproto/rpc_sender.h \ - ./SourceFiles/mtproto/scheme_auto.h \ - ./SourceFiles/mtproto/session.h \ - ./SourceFiles/overview/overview_layout.h \ - ./SourceFiles/platform/platform_main_window.h \ + ./SourceFiles/data/data_abstract_structure.h \ + ./SourceFiles/data/data_drafts.h \ + ./SourceFiles/dialogs/dialogs_common.h \ + ./SourceFiles/dialogs/dialogs_indexed_list.h \ + ./SourceFiles/dialogs/dialogs_layout.h \ + ./SourceFiles/dialogs/dialogs_list.h \ + ./SourceFiles/dialogs/dialogs_row.h \ + ./SourceFiles/history/field_autocomplete.h \ + ./SourceFiles/history/history_common.h \ + ./SourceFiles/history/history_service_layout.h \ + ./SourceFiles/inline_bots/inline_bot_layout_internal.h \ + ./SourceFiles/inline_bots/inline_bot_layout_item.h \ + ./SourceFiles/inline_bots/inline_bot_result.h \ + ./SourceFiles/inline_bots/inline_bot_send_data.h \ + ./SourceFiles/intro/introwidget.h \ + ./SourceFiles/intro/introcode.h \ + ./SourceFiles/intro/introphone.h \ + ./SourceFiles/intro/intropwdcheck.h \ + ./SourceFiles/intro/introsignup.h \ + ./SourceFiles/intro/introstart.h \ + ./SourceFiles/mtproto/facade.h \ + ./SourceFiles/mtproto/auth_key.h \ + ./SourceFiles/mtproto/connection.h \ + ./SourceFiles/mtproto/connection_abstract.h \ + ./SourceFiles/mtproto/connection_auto.h \ + ./SourceFiles/mtproto/connection_http.h \ + ./SourceFiles/mtproto/connection_tcp.h \ + ./SourceFiles/mtproto/core_types.h \ + ./SourceFiles/mtproto/dcenter.h \ + ./SourceFiles/mtproto/file_download.h \ + ./SourceFiles/mtproto/rsa_public_key.h \ + ./SourceFiles/mtproto/rpc_sender.h \ + ./SourceFiles/mtproto/scheme_auto.h \ + ./SourceFiles/mtproto/session.h \ + ./SourceFiles/overview/overview_layout.h \ + ./SourceFiles/platform/platform_file_dialog.h \ + ./SourceFiles/platform/platform_main_window.h \ + ./SourceFiles/platform/linux/linux_gdk_helper.h \ ./SourceFiles/platform/linux/linux_libs.h \ - ./SourceFiles/platform/linux/main_window_linux.h \ - ./SourceFiles/profile/profile_actions_widget.h \ - ./SourceFiles/profile/profile_block_widget.h \ - ./SourceFiles/profile/profile_cover_drop_area.h \ - ./SourceFiles/profile/profile_cover.h \ - ./SourceFiles/profile/profile_fixed_bar.h \ - ./SourceFiles/profile/profile_info_widget.h \ - ./SourceFiles/profile/profile_inner_widget.h \ - ./SourceFiles/profile/profile_invite_link_widget.h \ - ./SourceFiles/profile/profile_members_widget.h \ - ./SourceFiles/profile/profile_section_memento.h \ - ./SourceFiles/profile/profile_settings_widget.h \ - ./SourceFiles/profile/profile_shared_media_widget.h \ - ./SourceFiles/profile/profile_userpic_button.h \ - ./SourceFiles/profile/profile_widget.h \ - ./SourceFiles/pspecific.h \ - ./SourceFiles/serialize/serialize_common.h \ - ./SourceFiles/serialize/serialize_document.h \ - ./SourceFiles/ui/buttons/history_down_button.h \ - ./SourceFiles/ui/buttons/left_outline_button.h \ - ./SourceFiles/ui/buttons/peer_avatar_button.h \ - ./SourceFiles/ui/buttons/round_button.h \ - ./SourceFiles/ui/style/style_core.h \ - ./SourceFiles/ui/style/style_core_color.h \ - ./SourceFiles/ui/style/style_core_font.h \ - ./SourceFiles/ui/style/style_core_icon.h \ - ./SourceFiles/ui/style/style_core_types.h \ - ./SourceFiles/ui/text/text.h \ - ./SourceFiles/ui/text/text_block.h \ - ./SourceFiles/ui/text/text_entity.h \ - ./SourceFiles/ui/toast/toast.h \ - ./SourceFiles/ui/toast/toast_manager.h \ - ./SourceFiles/ui/toast/toast_widget.h \ - ./SourceFiles/ui/animation.h \ - ./SourceFiles/ui/boxshadow.h \ - ./SourceFiles/ui/button.h \ - ./SourceFiles/ui/popupmenu.h \ - ./SourceFiles/ui/countryinput.h \ - ./SourceFiles/ui/emoji_config.h \ - ./SourceFiles/ui/filedialog.h \ - ./SourceFiles/ui/flatbutton.h \ - ./SourceFiles/ui/flatcheckbox.h \ - ./SourceFiles/ui/flatinput.h \ - ./SourceFiles/ui/flatlabel.h \ - ./SourceFiles/ui/flattextarea.h \ - ./SourceFiles/ui/images.h \ - ./SourceFiles/ui/inner_dropdown.h \ - ./SourceFiles/ui/scrollarea.h \ - ./SourceFiles/ui/twidget.h \ - ./SourceFiles/window/main_window.h \ - ./SourceFiles/window/section_memento.h \ - ./SourceFiles/window/section_widget.h \ - ./SourceFiles/window/slide_animation.h \ - ./SourceFiles/window/top_bar_widget.h + ./SourceFiles/platform/linux/file_dialog_linux.h \ + ./SourceFiles/platform/linux/main_window_linux.h \ + ./SourceFiles/profile/profile_actions_widget.h \ + ./SourceFiles/profile/profile_block_widget.h \ + ./SourceFiles/profile/profile_cover_drop_area.h \ + ./SourceFiles/profile/profile_cover.h \ + ./SourceFiles/profile/profile_fixed_bar.h \ + ./SourceFiles/profile/profile_info_widget.h \ + ./SourceFiles/profile/profile_inner_widget.h \ + ./SourceFiles/profile/profile_invite_link_widget.h \ + ./SourceFiles/profile/profile_members_widget.h \ + ./SourceFiles/profile/profile_section_memento.h \ + ./SourceFiles/profile/profile_settings_widget.h \ + ./SourceFiles/profile/profile_shared_media_widget.h \ + ./SourceFiles/profile/profile_userpic_button.h \ + ./SourceFiles/profile/profile_widget.h \ + ./SourceFiles/pspecific.h \ + ./SourceFiles/serialize/serialize_common.h \ + ./SourceFiles/serialize/serialize_document.h \ + ./SourceFiles/ui/buttons/history_down_button.h \ + ./SourceFiles/ui/buttons/left_outline_button.h \ + ./SourceFiles/ui/buttons/peer_avatar_button.h \ + ./SourceFiles/ui/buttons/round_button.h \ + ./SourceFiles/ui/style/style_core.h \ + ./SourceFiles/ui/style/style_core_color.h \ + ./SourceFiles/ui/style/style_core_font.h \ + ./SourceFiles/ui/style/style_core_icon.h \ + ./SourceFiles/ui/style/style_core_types.h \ + ./SourceFiles/ui/text/text.h \ + ./SourceFiles/ui/text/text_block.h \ + ./SourceFiles/ui/text/text_entity.h \ + ./SourceFiles/ui/toast/toast.h \ + ./SourceFiles/ui/toast/toast_manager.h \ + ./SourceFiles/ui/toast/toast_widget.h \ + ./SourceFiles/ui/animation.h \ + ./SourceFiles/ui/boxshadow.h \ + ./SourceFiles/ui/button.h \ + ./SourceFiles/ui/popupmenu.h \ + ./SourceFiles/ui/countryinput.h \ + ./SourceFiles/ui/emoji_config.h \ + ./SourceFiles/ui/filedialog.h \ + ./SourceFiles/ui/flatbutton.h \ + ./SourceFiles/ui/flatcheckbox.h \ + ./SourceFiles/ui/flatinput.h \ + ./SourceFiles/ui/flatlabel.h \ + ./SourceFiles/ui/flattextarea.h \ + ./SourceFiles/ui/images.h \ + ./SourceFiles/ui/inner_dropdown.h \ + ./SourceFiles/ui/scrollarea.h \ + ./SourceFiles/ui/twidget.h \ + ./SourceFiles/window/main_window.h \ + ./SourceFiles/window/section_memento.h \ + ./SourceFiles/window/section_widget.h \ + ./SourceFiles/window/slide_animation.h \ + ./SourceFiles/window/top_bar_widget.h win32 { SOURCES += \ - ./SourceFiles/pspecific_win.cpp \ - ./SourceFiles/platform/win/windows_app_user_model_id.cpp \ - ./SourceFiles/platform/win/windows_dlls.cpp \ - ./SourceFiles/platform/win/windows_event_filter.cpp \ - ./SourceFiles/platform/win/windows_toasts.cpp + ./SourceFiles/pspecific_win.cpp \ + ./SourceFiles/platform/win/windows_app_user_model_id.cpp \ + ./SourceFiles/platform/win/windows_dlls.cpp \ + ./SourceFiles/platform/win/windows_event_filter.cpp \ + ./SourceFiles/platform/win/windows_toasts.cpp HEADERS += \ - ./SourceFiles/pspecific_win.h \ - ./SourceFiles/platform/win/windows_app_user_model_id.h \ - ./SourceFiles/platform/win/windows_dlls.h \ - ./SourceFiles/platform/win/windows_event_filter.h \ - ./SourceFiles/platform/win/windows_toasts.h + ./SourceFiles/pspecific_win.h \ + ./SourceFiles/platform/win/windows_app_user_model_id.h \ + ./SourceFiles/platform/win/windows_dlls.h \ + ./SourceFiles/platform/win/windows_event_filter.h \ + ./SourceFiles/platform/win/windows_toasts.h } winrt { SOURCES += \ - ./SourceFiles/pspecific_winrt.cpp \ - ./SourceFiles/platform/winrt/main_window_winrt.cpp + ./SourceFiles/pspecific_winrt.cpp \ + ./SourceFiles/platform/winrt/main_window_winrt.cpp HEADERS += \ - ./SourceFiles/pspecific_winrt.h \ - ./Sourcefiles/platform/winrt/main_window_winrt.h + ./SourceFiles/pspecific_winrt.h \ + ./Sourcefiles/platform/winrt/main_window_winrt.h } macx { SOURCES += \ - ./SourceFiles/pspecific_mac.cpp + ./SourceFiles/pspecific_mac.cpp HEADERS += \ - ./SourceFiles/pspecific_mac.h + ./SourceFiles/pspecific_mac.h OBJECTIVE_SOURCES += \ - ./SourceFiles/pspecific_mac_p.mm \ - ./SourceFiles/platform/mac/main_window_mac.mm + ./SourceFiles/pspecific_mac_p.mm \ + ./SourceFiles/platform/mac/main_window_mac.mm HEADERS += \ - ./SourceFiles/pspecific_mac_p.h \ - ./SourceFiles/platform/mac/main_window_mac.h + ./SourceFiles/pspecific_mac_p.h \ + ./SourceFiles/platform/mac/main_window_mac.h } SOURCES += \ - ./ThirdParty/minizip/zip.c \ - ./ThirdParty/minizip/ioapi.c + ./ThirdParty/minizip/zip.c \ + ./ThirdParty/minizip/ioapi.c CONFIG += precompile_header @@ -450,19 +455,19 @@ QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-v QMAKE_CFLAGS_WARN_ON += -Wno-unused-result -Wno-unused-parameter -Wno-unused-variable -Wno-switch -Wno-comment -Wno-unused-but-set-variable CONFIG(release, debug|release) { - QMAKE_CXXFLAGS_RELEASE -= -O2 - QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g - QMAKE_LFLAGS_RELEASE -= -O1 - QMAKE_LFLAGS_RELEASE += -Ofast -flto -g -rdynamic -static-libstdc++ + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE += -Ofast -flto -fno-strict-aliasing -g + QMAKE_LFLAGS_RELEASE -= -O1 + QMAKE_LFLAGS_RELEASE += -Ofast -flto -g -rdynamic -static-libstdc++ } # Linux 32bit fails Release link with Link-Time Optimization: virtual memory exhausted unix { - !contains(QMAKE_TARGET.arch, x86_64) { - CONFIG(release, debug|release) { - QMAKE_CXXFLAGS_RELEASE -= -flto - QMAKE_LFLAGS_RELEASE -= -flto - } - } + !contains(QMAKE_TARGET.arch, x86_64) { + CONFIG(release, debug|release) { + QMAKE_CXXFLAGS_RELEASE -= -flto + QMAKE_LFLAGS_RELEASE -= -flto + } + } } CONFIG(debug, debug|release) { QMAKE_LFLAGS_DEBUG += -g -rdynamic -static-libstdc++ @@ -471,22 +476,23 @@ CONFIG(debug, debug|release) { include(qt_static.pri) INCLUDEPATH += \ - /usr/local/include\ - /usr/local/include/opus\ - ./SourceFiles\ - ./GeneratedFiles\ - ./ThirdParty/minizip\ - ./../../Libraries/breakpad/src + /usr/local/include\ + /usr/local/include/opus\ + ./SourceFiles\ + ./GeneratedFiles\ + ./ThirdParty/minizip\ + ./../../Libraries/breakpad/src INCLUDEPATH += "/usr/include/libappindicator-0.1" +#INCLUDEPATH += "/usr/include/gtk-3.0" INCLUDEPATH += "/usr/include/gtk-2.0" +INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include" +INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include" INCLUDEPATH += "/usr/include/glib-2.0" INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include" INCLUDEPATH += "/usr/lib/i386-linux-gnu/glib-2.0/include" INCLUDEPATH += "/usr/include/cairo" INCLUDEPATH += "/usr/include/pango-1.0" -INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include" -INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include" INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0" INCLUDEPATH += "/usr/include/atk-1.0" @@ -502,21 +508,21 @@ LIBS += /usr/local/lib/libxkbcommon.a LIBS += ./../../../Libraries/breakpad/src/client/linux/libbreakpad_client.a RESOURCES += \ - ./Resources/telegram.qrc \ - ./Resources/telegram_linux.qrc \ - ./Resources/telegram_emojis.qrc + ./Resources/telegram.qrc \ + ./Resources/telegram_linux.qrc \ + ./Resources/telegram_emojis.qrc OTHER_FILES += \ - ./Resources/basic_types.style \ - ./Resources/basic.style \ - ./Resources/all_files.style \ - ./Resources/langs/lang.strings \ - ./Resources/langs/lang_it.strings \ - ./Resources/langs/lang_es.strings \ - ./Resources/langs/lang_de.strings \ - ./Resources/langs/lang_nl.strings \ - ./Resources/langs/lang_pt_BR.strings \ - ./SourceFiles/dialogs/dialogs.style \ - ./SourceFiles/history/history.style \ - ./SourceFiles/overview/overview.style \ - ./SourceFiles/profile/profile.style + ./Resources/basic_types.style \ + ./Resources/basic.style \ + ./Resources/all_files.style \ + ./Resources/langs/lang.strings \ + ./Resources/langs/lang_it.strings \ + ./Resources/langs/lang_es.strings \ + ./Resources/langs/lang_de.strings \ + ./Resources/langs/lang_nl.strings \ + ./Resources/langs/lang_pt_BR.strings \ + ./SourceFiles/dialogs/dialogs.style \ + ./SourceFiles/history/history.style \ + ./SourceFiles/overview/overview.style \ + ./SourceFiles/profile/profile.style diff --git a/Telegram/qt_static.pri b/Telegram/qt_static.pri index c3e1b873b..9d0db3aff 100644 --- a/Telegram/qt_static.pri +++ b/Telegram/qt_static.pri @@ -16,5 +16,6 @@ isEmpty(QT_TDESKTOP_VERSION) { INCLUDEPATH += $${QT_TDESKTOP_PATH}/include/QtGui/$${QT_TDESKTOP_VERSION}/QtGui \ $${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION}/QtCore \ + $${QT_TDESKTOP_PATH}/include/QtCore/$${QT_TDESKTOP_VERSION} \ $${QT_TDESKTOP_PATH}/include